Md dosyaları düzenleme ve ölü kodlar kaldırıldı
This commit is contained in:
parent
ae226d359b
commit
677a62bd79
11 changed files with 148 additions and 118 deletions
10
.github/instructions/ai.instructions.md
vendored
10
.github/instructions/ai.instructions.md
vendored
|
|
@ -362,8 +362,10 @@ MCP (`/mcp`, `Sozsoft.Mcp` module) — expose ListForm data/queries to an extern
|
|||
(Claude, ChatGPT, or an OAuth-registered MCP client) without new code: configure a server row
|
||||
on the **MCP Servers** screen (`App.DeveloperKit.McpServers`, §12.2 of
|
||||
`lowcode-reference.instructions.md`) with its allowed tools and tenant scope; queries always run
|
||||
on the calling tenant's own database. Tenant users are read-only over MCP (schema tools,
|
||||
`query_list`, `run_select`); writing and development tools are host-only. A
|
||||
on the calling tenant's own database. Tenant users read and write data over MCP but cannot develop
|
||||
(`McpToolNames.TenantTools`: schema tools, `query_list`, `run_select`, `insert_row`/`update_row`/`delete_row`
|
||||
— row writes go through the screen's C/U/D contract and need `.Write`); development tools,
|
||||
`list_queries` and `run_query` are host-only. A
|
||||
request to "let an agent query/update X" is a Decision Flow §1 (ListForm) request first — MCP
|
||||
only gates which of the existing screens/queries an already-authorized client may reach; it
|
||||
never grants access beyond the calling user's own ListForm/query permissions. Ayrıntı:
|
||||
|
|
@ -879,7 +881,7 @@ Default is `List`, so older seed files that lack it keep working.
|
|||
|
||||
| Kind | Produces | Menu URL | Child permissions |
|
||||
| --- | --- | --- | --- |
|
||||
| `List` | ListForm + ListFormFields + Route + Menu + Permissions + language keys | `/admin/list/{ListFormCode}` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| `List` | ListForm + ListFormFields + Menu + Permissions + language keys (no Route record; the generic `/admin/list/{code}` route serves it) | `/admin/list/{ListFormCode}` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| `Custom` | Menu + Permissions + language keys; the screen is the selected Custom Component | the component's `RoutePath` | `.Create`, `.Update`, `.Delete` only |
|
||||
|
||||
`Export` / `Import` / `Note` exist only in the ListForm ecosystem. Never propose them on the
|
||||
|
|
@ -891,7 +893,7 @@ embedded elsewhere as a SubGrid/part. Default is `true`.
|
|||
|
||||
### 32.4 Permission group selection
|
||||
|
||||
The wizard's permission group comes from a select list backed by `GetWizardPermissionGroups`.
|
||||
The wizard's permission group comes from a select list backed by `ListFormWizardAppService.GetPermissionGroups` (`/api/app/list-form-wizard/permission-groups`).
|
||||
Display names are read from the language key whose name equals the group name.
|
||||
|
||||
- Selecting an existing group fills `PermissionGroupEn/Tr` (seed file: `Language.PermissionGroupEn/Tr`);
|
||||
|
|
|
|||
2
.github/instructions/dotnet.instructions.md
vendored
2
.github/instructions/dotnet.instructions.md
vendored
|
|
@ -31,7 +31,7 @@ Kural:
|
|||
|
||||
- Nullable, proje bazında ve bilinçli olarak açılır (`<Nullable>enable</Nullable>`).
|
||||
Şu an açık olanlar: `Sozsoft.Platform.Application`, `Sozsoft.Notifications.*`,
|
||||
test projeleri.
|
||||
`Sozsoft.Mcp.*`, test projeleri.
|
||||
- **Entity taşıyan projelerde** (`*.Domain`) nullable açılacaksa, aynı PR'da
|
||||
`dotnet ef migrations add` çıktısı gözden geçirilir; şema değişikliği isteniyorsa
|
||||
kabul edilir, istenmiyorsa kolon zorunluluğu `PlatformDbContext` içinde
|
||||
|
|
|
|||
36
.github/instructions/lowcode.instructions.md
vendored
36
.github/instructions/lowcode.instructions.md
vendored
|
|
@ -482,7 +482,8 @@ ya da ziyaretçiye açık yeni bir fiziksel sayfa ürettiğinde.
|
|||
|
||||
**Genel varsayılanlar kayıtta değil ayardadır:** site adresi, site adı, varsayılan başlık ve
|
||||
açıklama, paylaşım görseli, Twitter hesabı, diller, robots yönergesi, Google doğrulaması,
|
||||
sosyal hesaplar ve sitemap anahtarı `App.SiteManagement.Seo.*` ayarlarındadır
|
||||
sosyal hesaplar, varsayılan anahtar kelimeler (`DefaultKeywords`), sitemap anahtarı (`SitemapEnabled`) ve
|
||||
sitemap dışı yollar (`SitemapExcludePaths`) `App.SiteManagement.Seo.*` ayarlarındadır
|
||||
(`configs/seeds/host/data/App.SettingDefinitions.json`). Bir değer bütün site için geçerliyse
|
||||
oraya yazılır, her yola tekrarlanmaz. Site kökü (`/`) hiçbir kayıt taşımaz; doğrudan bu
|
||||
varsayılanlardan beslenir.
|
||||
|
|
@ -605,7 +606,8 @@ talebin metnini döndürür. Başlık birden fazla talebe uyuyorsa Id ister. `St
|
|||
- `Timesheets` — **sunucu yazar, model hiçbir şey yapmaz.** `get_dev_request` / `start_dev_request`
|
||||
talebi kullanıcının etkin talebi yapar; ardından yapılan her MCP yazma işlemi (`create_table`,
|
||||
`deploy_wizard`, `delete_wizard`, `save_component`, `delete_component`, `insert_row` /
|
||||
`update_row` / `delete_row`, `save_dev_request_analysis`) o talebe bir satır ekler
|
||||
`update_row` / `delete_row`, `save_dev_request_analysis`, `append_dev_request_note`,
|
||||
`add_dev_request_subtasks`) o talebe bir satır ekler
|
||||
(`IMcpDevRequestTimesheetRecorder`). Açıklama `App.Mcp.Timesheet.*` dil anahtarından **Türkçe**
|
||||
üretilir ("Hr_T_Doctor tablosu oluşturuldu"), süre önceki satırdan ya da talebin açıldığı andan bu
|
||||
yana ölçülür (en az 1 dakika, saat olarak), çalışan bağlanan kullanıcı, tarih bugündür.
|
||||
|
|
@ -901,7 +903,7 @@ hiçbir şey silmez**. Tek çıktısı seed dosyalarıdır:
|
|||
| `wizard/{WizardName}.json` | Ekranın `ListForm`/`Fields` sözleşmesi, wizard cevapları, `InsertedRecords`, `Pending` |
|
||||
| `data/App.Menus.Module.json`, `data/App.Menus.Menu.json` | Modül, üst menü, ekranın menüsü |
|
||||
| `data/Abp.Identity.PermissionGroups.json`, `data/Abp.Identity.Permissions.json` | İzin grubu, okuma yetkisi ve alt yetkileri |
|
||||
| `data/App.Languages.LanguageText.json` | Menü, başlık, açıklama, grup ve alan başlıklarının EN + TR metinleri (`Id` iş anahtarından v5 GUID, `SeedRowIds.LanguageText`) |
|
||||
| `data/App.Languages.LanguageText.json` | Menü, başlık, açıklama, grup, alan başlıkları ve `Language.Texts` anahtarlarının (widget başlıkları) EN + TR metinleri (`Id` iş anahtarından v5 GUID, `SeedRowIds.LanguageText`) |
|
||||
|
||||
Satırları `WizardSeedRowStore` yazar; anahtarlar `WizardSeedRowKeys`'ten gelir (export aynı
|
||||
listeyle toplar). **Sahiplik:** bir satır ne veritabanında ne dosyada varsa ya da önceki sürüm ona
|
||||
|
|
@ -942,7 +944,8 @@ sürümünü taşır.
|
|||
"Menu": { "MenuCode": "…", "MenuOrder": 2, "MenuUrl": "…", "MenuIcon": "…",
|
||||
"MenuParentPath": [ { "Code": "…", "Icon": "…", "En": "…", "Tr": "…" } ], // yalnızca derin yolda
|
||||
"MenuParentCode": "…", "MenuParentIcon": "…" }, // "CreateMenu": false ise eklenir
|
||||
"Language": { "MenuEn": "…", /* Menu/Title/Desc/MenuParent/PermissionGroup · EN + TR */ },
|
||||
"Language": { "MenuEn": "…", /* Menu/Title/Desc/MenuParent/PermissionGroup · EN + TR */
|
||||
"Texts": [ { "Key": "…", "En": "…", "Tr": "…" } ] }, // Texts yalnızca doluysa
|
||||
"Groups": [ { "Items": [ { "FieldName": "…", "CaptionName": "…",
|
||||
"En": "…", "Tr": "…" } ] } ] // grup Caption/ColCount yok
|
||||
},
|
||||
|
|
@ -993,7 +996,7 @@ düzenleme izinleri, görünüm option blokları, alt formlar, widget'lar, iş a
|
|||
|
||||
Dosyada wizard alanları üç başlık altında toplanır — `Menu` (menü kaydı), `Language` (dil
|
||||
metinleri), `Groups` (alan başlıklarının dil karşılıkları); geri kalanı kök seviyededir.
|
||||
Gruplama ile `ListFormCode → WizardCode` ve `MenuParentModuleId → ModuleId` adlandırmaları
|
||||
Gruplama ile `ListFormCode → WizardCode`, `MenuParentModuleId → ModuleId` ve `LanguageTexts → Language.Texts` adlandırmaları
|
||||
yalnızca **dosya biçimidir**; C#
|
||||
sözleşmesi (`ListFormWizardDto`) düzdür ve dosya okunurken düzleştirilir
|
||||
(`WizardSeedFileDto.FromSeedJson` ↔ `ToSeedJson`). Aşağıdaki tablolar C# alan adlarını kullanır.
|
||||
|
|
@ -1671,8 +1674,9 @@ Silme ucu (`DeleteFile`) her kaydın akıbetini (`Deleted` / `Kept` + kullananla
|
|||
Düzenleme (`EditFileName`) bu sınıfı çağırmaz; önceki sürümün kayıtlarını migrate kaldırır (§4.0).
|
||||
Wizard'ın yarattığı modül `InsertedRecords.ModuleIds` ile izlenir.
|
||||
|
||||
Silme yolunda ekranın veri aynası (`ListForm.SeedFilePath` → `data/{ListFormCode}.json` ya da
|
||||
klasörü) ekranla birlikte silinir; ekransız uygulanamaz.
|
||||
Kurulu wizard silinirken ekranın veri aynası (`ListForm.SeedFilePath` → `data/{ListFormCode}.json` ya da
|
||||
klasörü) ekranla birlikte silinir; ekransız uygulanamaz. Migrate bekleyen wizard'da ayna yalnızca ekran
|
||||
hiç kurulmamışsa silinir (MCP demo satırları); kurulu ekranın aynası veritabanındaki satırların kaydıdır, kalır.
|
||||
|
||||
**Ekranın tablosu** wizard'ın ürettiği bir kayıt değildir (tasarımcı ya da `create_table` ile
|
||||
ayrıca kurulur, `InsertedRecords`'ta yoktur) ve **kendiliğinden silinmez**. Silme onayı önce
|
||||
|
|
@ -2124,8 +2128,9 @@ opsiyonel `ApprovalDateFieldName`, `ApprovalDescriptionFieldName`, `ApprovalIsFi
|
|||
dönsün). Onay düğümleri (`Criteria`) görsel akış tasarımcısında kurulur ve `ListFormWorkflow`
|
||||
kayıtlarına gider (§4.7).
|
||||
|
||||
**Adım 12 — Deploy.** Sol tarafta tüm adımların özeti, sağda üretim log'u. Üretim sırası —
|
||||
seed dosyası uygulanırken `WizardDataSeeder`'ın izlediği sıranın aynısıdır:
|
||||
**Adım 12 — Deploy.** Sol tarafta tüm adımların özeti, sağda üretim log'u. Log, deploy'un seed
|
||||
dosyalarına yazdığı bölümleri sırayla gösterir; migrate'te `WizardDataSeeder` ekrana özgü kayıtları,
|
||||
ardından `ListFormSeedDataApplier` menü/yetki/dil satırlarını kurar (§4.0):
|
||||
|
||||
1. Konfigürasyon doğrulama
|
||||
2. Menü kaydı (`CreateMenu: false` ise atlanır)
|
||||
|
|
@ -2134,10 +2139,11 @@ seed dosyası uygulanırken `WizardDataSeeder`'ın izlediği sıranın aynısıd
|
|||
5. List yolunda: veri kaynağı → ListForm → alan grupları · Custom yolunda: bileşen bağlama
|
||||
6. Deploy + tamamlandı
|
||||
|
||||
Başarıda sihirbaz `/admin/list/{ListFormCode}`'a yönlendirir ve seed dosyası
|
||||
`configs/seeds/{kapsam}/wizard/` altına yazılmış olur. **Düzenleme modu** Wizard Manager'dan
|
||||
`EditFileName` ile açılır: aynı adımlar dolu gelir, kaydetmede önce eski dosya ve
|
||||
`InsertedRecords` kayıtları silinir (§4.5).
|
||||
Başarıda sihirbaz "Migrate bekliyor" bildirimiyle Wizard Manager'a döner (ekran henüz kurulu
|
||||
değildir; DB Migrate ile kurulur) ve seed dosyası `configs/seeds/{kapsam}/wizard/` altına yazılmış
|
||||
olur. **Düzenleme modu** Wizard Manager'dan `EditFileName` ile açılır: aynı adımlar dolu gelir,
|
||||
kaydetmede dosyalar cevaptan yeniden yazılır; önceki sürümün kayıtları `Pending.Replaced`'a alınır,
|
||||
veritabanına dokunulmaz — kaldırma ve yeniden kurulum DB Migrate'tedir (§4.0).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -2471,7 +2477,7 @@ Preset mevcut JSON ile **birleşir**, diğer ayarları silmez; aynı anahtar var
|
|||
| TagBox anında seçim | `showSelectionControls`, `applyValueMode:instantly`, `searchEnabled` |
|
||||
| GridBox tek/çok seçim | `columns`, `selectionMode`, `filterRowVisible`, `height`, `width` |
|
||||
| Çoklu görsel | `width`, `height`, `multiple`, `accept:image/*` |
|
||||
| HTML tam araç çubuğu | `toolbar.items` (tam liste), `toolbar.multiline`, `mediaResizing`, `imageUpload` |
|
||||
| HTML tam araç çubuğu | `htmlEditorOptions.ts` varsayılanı: `toolbar.items` (tam liste), `toolbar.multiline`, `mediaResizing`, `imageUpload` (`tabs: file/url`, base64), `tableResizing`, `tableContextMenu` — boş `editorOptions` da aynı varsayılanı alır |
|
||||
| Yükseklik 100 / 200 | `{"height":100}` · `{"height":200}` |
|
||||
| Barkod okutma butonu | `buttons[]` — kamera ikonlu buton; `onClick` = `"@SCAN_BARCODE"` token'ı. Yalnız `dxTextBox`. Token'ı `editingForm.ts` kamera diyaloğuna bağlar, okunan kod alana yazılır. HTTPS şart. |
|
||||
| Kamerayla foto çek | `{"accept":"image/*","capture":"environment"}` — yalnız `dxImageUpload`. Mobilde dosya seçici yerine **yalnızca** kamera açılır (`user` = ön kamera); masaüstünde yok sayılır. Ayarlanmazsa dokunmatik cihazda dosya seçicinin yanına ayrı bir kamera butonu gelir, yani ikisi birden kullanılabilir — bu kalıp kamerayı **zorunlu** kılmak içindir. |
|
||||
|
|
@ -2489,7 +2495,7 @@ Preset mevcut JSON ile **birleşir**, diğer ayarları silmez; aynı anahtar var
|
|||
| Telefon | `EditorOptions.Phone()` | global format + maske + örnek |
|
||||
| Kaydırıcı | `EditorOptions.Slider()` | `{"tooltip":{"enabled":true}}` |
|
||||
| Görsel yükleme | `EditorOptions.ImageUpload(multiple: true, 80, 80)` | |
|
||||
| Zengin metin | `EditorOptions.Html(240)` | tam araç çubuğu + `encodeHtml` |
|
||||
| Zengin metin | `EditorOptions.Html(240)` | `htmlEditorOptions.ts` varsayılanıyla aynı bloklar (tam araç çubuğu, `imageUpload`, `mediaResizing`, `tableResizing`, `tableContextMenu`; biri değişirse diğeri de değişir) + `encodeHtml` + `elementAttr` `min-height:240px` (sabit yükseklik değil; içerikle büyür) |
|
||||
|
||||
Akıcı ekler: `.Placeholder()`, `.MaxLength()`, `.Height(int\|string)`, `.Width(int\|string)`,
|
||||
`.Format()`, `.FixedPointFormat(p)`, `.DisplayFormat()`, `.DateSerializationFormat()`,
|
||||
|
|
|
|||
58
README.md
58
README.md
|
|
@ -533,7 +533,7 @@ eskisi gibi çalışır.
|
|||
|
||||
| `ComponentKind` | Üretilen | Menü URL'i | Yetkiler |
|
||||
| --- | --- | --- | --- |
|
||||
| `List` | ListForm + ListFormField + Route + Menu + Permission + dil anahtarları | `/admin/list/{ListFormCode}` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| `List` | ListForm + ListFormField (+ iş akışı) + Menu + Permission + dil anahtarları (rota üretilmez; genel `/admin/list/{ListFormCode}` rotası kullanılır) | `/admin/list/{ListFormCode}` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||
| `Custom` | Menü + Permission + dil anahtarları; ekran seçilen Custom Component'tir | Component'in `RoutePath` değeri | Yalnızca `.Create`, `.Update`, `.Delete` (Export/Import/Note ListForm'a özgüdür) |
|
||||
|
||||
**Menüsüz wizard (`CreateMenu = false`).** Menü (ve gerekiyorsa üst menü) kaydı hiç üretilmez;
|
||||
|
|
@ -542,7 +542,7 @@ ekranda SubGrid/parça olarak kullanılmak üzere tanımlanır. Alan varsayılan
|
|||
alanı taşımayan eski seed dosyaları etkilenmez.
|
||||
|
||||
**İzin grubu seçimi.** Menü adımında izin grubu bir seçim listesinden gelir
|
||||
(`GetWizardPermissionGroups`). Görünen adlar, grup adıyla aynı olan dil anahtarının metinlerinden
|
||||
(`ListFormWizardAppService.GetPermissionGroups`, `/api/app/list-form-wizard/permission-groups`). Görünen adlar, grup adıyla aynı olan dil anahtarının metinlerinden
|
||||
okunur; seçim yapıldığında `PermissionGroupEn/Tr` forma doldurulur. Yeni bir grup
|
||||
tanımlanırsa grup adıyla aynı dil anahtarına bu metinler yazılır; mevcut grup seçilip alanlar boş
|
||||
bırakılırsa sunucu veritabanındaki değeri geri yazar. Böylece seed dosyası her durumda iki dilli
|
||||
|
|
@ -556,12 +556,15 @@ Var olan bir ekranı düzenlemek için `/admin/listform/edit/{listFormCode}` —
|
|||
yapılandırması sekmeli bir editörde yönetilir (Veritabanı, Sütunlar, Filtreler, Düzenleme,
|
||||
Yetkiler, Alt Form, Pivot, Tree, Gantt, Scheduler, Todo, Widget, Workflow, Durum, Grafik sekmeleri).
|
||||
|
||||
**Wizard File Manager** (`/admin/listform/wizard` liste ekranı) üretilmiş seed dosyalarını yönetir:
|
||||
**Wizard File Manager** (`/admin/listform/wizardManager`; sihirbazın kendisi `/admin/listform/wizard`) üretilmiş seed dosyalarını yönetir:
|
||||
liste/kart görünümü arasında geçiş (tercih diğer listelerle aynı yerde, `admin.lists.states`
|
||||
altında saklanır), arama, düzenleme (dosyanın yerine geçen yeni bir çalıştırma), silme, veritabanı
|
||||
migrate tetikleme, dışa aktarma ve içe aktarma. Liste, wizard'ın ilk deploy damgasına
|
||||
(`Wizard.SeededAt`) göre **tersine** sıralıdır — en son üretilen ekran en üstte durur; damgası
|
||||
okunamayan dosyalar sona düşer. Butonlar `App.Listforms.Wizard.*` yetkileriyle gizlenir; asıl
|
||||
okunamayan dosyalar sona düşer. Silme, bağlı wizard'ı olan dosyada reddedilir; onay diyaloğu önce
|
||||
`DeleteAnalysis` ile düşürülebilecek tabloyu sorar, sonuç her kaydın akıbetiyle (`Deleted` / `Kept` +
|
||||
kullananlar / `NotFound`) rapor olarak gösterilir (`WizardRecordCleaner`, `WizardTableCleaner`;
|
||||
`lowcode.instructions.md` §4.5). Butonlar `App.Listforms.Wizard.*` yetkileriyle gizlenir; asıl
|
||||
kontrol `ListFormWizardAppService` üzerindedir.
|
||||
|
||||
### 7.7. İçe/dışa aktarma
|
||||
|
|
@ -869,8 +872,8 @@ tıklamak seçim yapar, sayfayı değiştirmez — tıklama yakalama evresinde d
|
|||
**Diğer notlar.** `PlatformIcon` tasarımcı dokümanındaki ikon adını çözer; `selectComponents.ts`
|
||||
`Select.componentAs` için saklanan adı (`ReactSelect`, `CreatableSelect`, `AsyncSelect`) gerçek
|
||||
bileşene çevirir — kanvas ve üretilen bileşenin aynı adı aynı şekilde yorumlamasını sağlayan tek
|
||||
nokta budur. Yeni bileşen `configs/seeds/host/data/App.DeveloperKit.CustomComponents/{Id}.json`
|
||||
içindeki bir satır olarak başlar.
|
||||
nokta budur. Yeni bileşen `configs/seeds/host/data/App.DeveloperKit.CustomComponents/` klasöründe
|
||||
kendi `{Id}.json` satır dosyası olarak başlar.
|
||||
|
||||
**Dinamik servis yaşam döngüsü:** `DynamicServiceCompiler` kodu derler →
|
||||
`DynamicAssemblyRegistrationService` assembly'yi tenant bağlamıyla kaydeder →
|
||||
|
|
@ -917,8 +920,9 @@ kendi aralarında 1'den. `PlatformPermissionAppService` sıralama anahtarını k
|
|||
zincirinden kurar, böylece çocuk her zaman ebeveyninin altında kalır. Değerler seed dosyalarındaki
|
||||
`Order` alanında tutulur ve Permissions / Permission Groups ekranlarından düzenlenebilir.
|
||||
Wizard deploy'u yeni grubu ve grubun yeni kök yetkisini (seed satırı olarak) veritabanı ile seed
|
||||
dosyasındaki kardeşlerin en büyük sırasının bir fazlasıyla, alt yetkileri Create/Update/Delete/Export/Import/Note dizilimiyle
|
||||
1'den yazar (`NextPermissionOrder`, `AbpPermissionsExtensions`).
|
||||
dosyasındaki kardeşlerin en büyük sırasının bir fazlasıyla, alt yetkileri `WizardSeedRowKeys.ChildPermissions` dizilimiyle
|
||||
(List: Create/Update/Delete/Export/Import/Note, Custom: Create/Update/Delete) 1'den yazar
|
||||
(`ListFormWizardAppService.WritePermissionGroupAsync` / `WritePermissionRowsAsync`).
|
||||
|
||||
Aksiyon yetkisi olan alt gruplar (UI tarafındaki karşılıkları `constants/permission.constant.ts`
|
||||
içindedir; oradaki kontroller yalnızca butonları gizler, asıl kontrol AppService'lerdedir):
|
||||
|
|
@ -948,7 +952,7 @@ içindedir; oradaki kontroller yalnızca butonları gizler, asıl kontrol AppSer
|
|||
| **Sozsoft.MailQueue** | Şablon (Scriban) tabanlı gövde üretimi, ek dosya yaşam döngüsü, kuyruk çalıştırma ve günlükleme. |
|
||||
| **Sozsoft.Sender** | Amazon SES (mail), Posta Güvercini (SMS), WhatsApp Cloud API, Rocket.Chat göndericileri. |
|
||||
| **Sozsoft.SqlQueryManager** | SQL nesne yönetimi, sorgu çalıştırma, tablo/kolon metadata'sı. |
|
||||
| **Sozsoft.Mcp** | MCP (Model Context Protocol) sunucusu: `/mcp` Streamable HTTP ucu, kiracı bazlı araç seti, şema keşfi, sorgu, veri yazma ve (host) tablo/ekran/bileşen geliştirme. Kiracı kullanıcısı yalnızca veri okur. Bkz. §13.9. |
|
||||
| **Sozsoft.Mcp** | MCP (Model Context Protocol) sunucusu: `/mcp` Streamable HTTP ucu, kiracı bazlı araç seti, şema keşfi, sorgu, veri yazma ve (host) tablo/ekran/bileşen geliştirme. Kiracı kullanıcısı veri okur ve ekranın C/U/D sözleşmesinden geçerek satır yazar; geliştirme araçları yalnızca host'tadır. Bkz. §13.9. |
|
||||
|
||||
### 10.2. Uygulama servisleri (`api/src/Sozsoft.Platform.Application`)
|
||||
|
||||
|
|
@ -1003,7 +1007,7 @@ DeveloperKit > Custom Components (Visual Designer) üzerinden değişir. Aynı y
|
|||
ile paylaşan custom component kazanır; karşılığı olan dosyası bulunmayan rota kaydı ise hiç
|
||||
yüklenmez (`hasPhysicalComponent`) — seeder yalnızca eklediği için eski kayıtlar veritabanında
|
||||
kalsa bile ekran patlamaz. Seed: `configs/seeds/host/data/App.DeveloperKit.CustomComponents/{Id}.json`;
|
||||
bileşenin ayrı dosyası yoktur, her bileşen bu dosyada bir satırdır.
|
||||
ekran klasör modundadır, her bileşen kendi satır dosyasındadır (dosya adı satırın `Id`'si).
|
||||
|
||||
Runtime kapsamı sınırlıdır: bileşen kodundaki `import` satırları derlemede temizlenir,
|
||||
kullanılabilenler `React`, `ui` kit, `PlatformViewHost`, `apiService`, `axios`, `DOMPurify`,
|
||||
|
|
@ -1089,7 +1093,7 @@ Veriden beslenen public sayfalar (`/products`, `/checkout`, `/payment`, `/succes
|
|||
|
||||
| Parça | Nerede | Ne taşır |
|
||||
| --- | --- | --- |
|
||||
| Genel varsayılanlar | `App.SiteManagement.Seo.*` ayarları (Ayarlar ekranı, yetki `App.SiteManagement.Seo`) | Site adresi, site adı, varsayılan başlık/açıklama/paylaşım görseli, Twitter hesabı, diller, robots yönergesi, Google doğrulaması, sosyal hesaplar, sitemap anahtarı |
|
||||
| Genel varsayılanlar | `App.SiteManagement.Seo.*` ayarları (Ayarlar ekranı, yetki `App.SiteManagement.Seo`) | Site adresi, site adı, varsayılan başlık/açıklama/paylaşım görseli, Twitter hesabı, diller, robots yönergesi, Google doğrulaması, sosyal hesaplar, varsayılan anahtar kelimeler (`DefaultKeywords`), sitemap anahtarı (`SitemapEnabled`), sitemap dışı yollar (`SitemapExcludePaths`) |
|
||||
| Yol bazlı alanlar | Yolu tanımlayan kaydın `Seo*` kolonları: `Route` (`Sas_H_Route`, ekran **Menü Yönetimi › Route**) ve `CustomComponent` (`Sas_H_CustomComponent`, ekran **DeveloperKit › Custom Components**) | Yolun başlığı, açıklaması, anahtar kelimeleri, paylaşım görseli, kanonik adresi, `SeoNoIndex`, sitemap davranışı ve ek JSON-LD |
|
||||
| İstemci | `components/shared/SeoHead.tsx` | `title`, `description`, `robots`, `canonical`, `og:`/`twitter:` kartı, `og:locale:alternate` ve JSON-LD |
|
||||
|
||||
|
|
@ -1109,7 +1113,11 @@ Sayfanın kendi `SeoHead`'i, kabuğun (`PublicLayout`) `fallback` kaydını her
|
|||
`sitemap.xml` ve `robots.txt` aynı servisten üretilir (`SeoController`, anonim). Sitemap'in
|
||||
kaynakları: `Pub` menüleri, aktif custom component rotaları, yayınlanmış blog yazıları ve
|
||||
yolu tanımlayan kayıtların `Seo*` alanları; `/admin` yolları, parametreli rotalar (`/blog/:id`) ve
|
||||
`SeoNoIndex` işaretli yollar elenir. Arama motorları bu iki dosyayı **sitenin** kök dizininde aradığı için UI sunucusu her iki
|
||||
`SeoNoIndex` işaretli ya da `SeoIncludeInSitemap = false` olan yollar elenir.
|
||||
`App.SiteManagement.Seo.SitemapExcludePaths` (satır başına bir yol, sonu `*` ise önek) hem sitemap'ten
|
||||
düşer hem `robots.txt`'e `Disallow` olarak yazılır; `robots.txt` ayrıca `/admin/`, `/auth/`,
|
||||
`/checkout`, `/payment`, `/success` yollarını her zaman kapatır. `SitemapEnabled` kapalıyken
|
||||
`sitemap.xml` 404 döner ve robots'a `Sitemap:` satırı yazılmaz. Arama motorları bu iki dosyayı **sitenin** kök dizininde aradığı için UI sunucusu her iki
|
||||
yolu da API'ye geçirir (`vite.config.ts` > `seoProxy`, hem `server` hem `preview`); ayrı bir ters
|
||||
vekil kuralı gerekmez. `VITE_API_URL` tanımlı değilse proxy kurulmaz ve `ui/public/robots.txt`
|
||||
içindeki statik varsayılan geçerli kalır.
|
||||
|
|
@ -1276,21 +1284,23 @@ Bildirimin tamamı Administration menüsünde `App.Administration.Notifications`
|
|||
**Bildirim Türleri**, **Bildirim Kuralları**, **Bildirimler**, **Bildirim Şablonları**. Grup
|
||||
Agenda'nın üstündedir; Saas altında bildirim ekranı **yoktur**.
|
||||
|
||||
Tablolar kiracı kapsamındadır (`Adm_T_NotificationType`, `Adm_T_NotificationRule`,
|
||||
`Adm_T_Notification`; üçü de `IMultiTenant`). Her kiracı kendi türünü, kuralını ve kuyruğunu
|
||||
Tablolar kiracı kapsamındadır (`Adm_T_NotificationTemplate`, `Adm_T_NotificationType`,
|
||||
`Adm_T_NotificationRule`, `Adm_T_Notification`; dördü de `IMultiTenant`). Her kiracı kendi türünü, kuralını ve kuyruğunu
|
||||
görür; host kaydı (`TenantId = null`) yalnızca host oturumunda görünür. Yeni bir kiracı
|
||||
oluşturulduğunda varsayılan tür ve kural kümesi o kiracıya kopyalanır
|
||||
(`NotificationTenantDefaultsSeedContributor`): kaynak host kapsamındaki
|
||||
`data/App.Notifications.Notification{Types,Rules}.json` dosyalarıdır, satırlar **yeni
|
||||
kimliklerle** yazılır ve eşleşme ad üzerinden yapıldığı için ikinci çalıştırma bir şey eklemez.
|
||||
kimliklerle** yazılır ve eşleşme ad üzerinden yapıldığı için ikinci çalıştırma bir şey eklemez;
|
||||
şablonlar kopyalanmaz.
|
||||
|
||||
**Bildirimler** ekranı (`App.Notifications.Notification`) hem kuyruk günlüğü hem gönderim
|
||||
ekranıdır: liste kural motorunun ürettiklerini de gösterir, ekleme formu ise elle gönderimdir.
|
||||
Ayrı bir manuel gönderim kaydı yoktur — gönderimin kaydı bildirimin kendisidir. Ekleme anında
|
||||
yazma işi `list-form-dynamic-api/notification-insert` ucuna gider (`InsertServiceAddress`); uç
|
||||
seçilen alıcı × kanal açılımını `INotificationManager.SendManualNotificationAsync` ile kuyruğa
|
||||
yazar — yani Bildirim Kuralları ekranındaki elle gönderimle **aynı yol**, tek fark alıcı
|
||||
kümesinin kurallardan değil ekrandan gelmesi. Güncelleme kapalıdır, silme kaydı kaldırır.
|
||||
yazar. Bildirim Kuralları ekranındaki `CreateNotification` diyaloğu ise aynı yöneticinin
|
||||
`SendNotificationAsync` yolunu kullanır: türün kurallarını işletir ve kullanıcı tercihini dikkate
|
||||
alır; bu uç alıcıyı ekrandan alır ve tercihi okumaz. Güncelleme kapalıdır, silme kaydı kaldırır.
|
||||
|
||||
Formdaki `NotificationChannel` ve `UserId` alanları listede tek değerlidir (her satır bir
|
||||
alıcı × kanal), formda `dxTagBox` ile çoklu seçilir; tipli DTO yolunda çoklu değeri
|
||||
|
|
@ -1414,12 +1424,14 @@ liste süzgeci ve çağrı kapısı aynı kuralı kullanır.
|
|||
| `save_dev_request_analysis` | `Backlog` ya da `Analysis` durumundaki talebin analizini (HTML) `Analysis` kolonuna yazar — var olanı değiştirir — ve talebi `Analysis` durumuna alır; diğer durumları reddeder. `Description`'a dokunmaz. Analizin standardı `lowcode.instructions.md` §0.12. `.Write` + `App.DevRequests.Update` ister. |
|
||||
| `add_dev_request_subtasks` | Talebin `SubTasks` listesine tamamlanmış satırlar ekler: model yalnızca başlığı verir, atanan kişi bağlanan kullanıcının adı (`userName`), bitiş tarihi bugün (`yyyy-MM-dd`) olarak sunucuda yazılır; var olan satırlar korunur. `.Write` + `App.DevRequests.Update` ister. |
|
||||
| `append_dev_request_note` | Talebin `Analysis` kolonunun sonuna HTML ekler (üretim sonuç notu); `Description` talebin yazıldığı hâliyle kalır. İkisi de `update_row` ile yazılmaz — açıklama base64 görsel taşır. `.Write` + `App.DevRequests.Update` ister. |
|
||||
| `list_components` / `get_component` / `save_component` / `delete_component` | Custom component'ler `ICustomComponentAppService` üzerinden; seed senkronu ve `DataSources` çözümü aynen çalışır. `save_component` ada göre ekler/günceller, tasarımcı belgesi (`Props.visualDesigner`, `sourceMode ≠ code`) taşıyan bileşene kod yazmayı reddeder — kod belgeden üretildiği için tasarımcıdaki ilk kayıtta ezilirdi. |
|
||||
|
||||
**Timesheets.** Talebin `Timesheets` listesini sunucu doldurur (`IMcpDevRequestTimesheetRecorder`):
|
||||
`get_dev_request` / `start_dev_request` talebi kullanıcının etkin talebi yapar (dağıtık önbellek,
|
||||
`McpDevRequestActivityCacheItem`, 12 saat); sonraki her MCP yazma işlemi (`create_table`,
|
||||
`deploy_wizard`, `delete_wizard`, `save_component`, `delete_component`, satır araçları,
|
||||
`save_dev_request_analysis`) o talebe bir satır ekler. Açıklama `App.Mcp.Timesheet.*` anahtarından
|
||||
`save_dev_request_analysis`, `append_dev_request_note`, `add_dev_request_subtasks`) o talebe bir satır
|
||||
ekler; talebi açan `start_dev_request` yazmaz. Açıklama `App.Mcp.Timesheet.*` anahtarından
|
||||
Türkçe üretilir, süre önceki satırdan ya da talebin açıldığı andan ölçülür (en az 1 dakika, saat
|
||||
olarak), çalışan bağlanan kullanıcı, tarih bugündür. Etkin talep yoksa satır yazılmaz; bozuk bir
|
||||
`Timesheets` değeri işlemi geri almaz, yalnızca satır atlanır ve log'a düşer.
|
||||
|
|
@ -1454,7 +1466,6 @@ değilse sunucu reddeder ve hiçbir şey üretilmez.
|
|||
başlıkta komut yerine Id ya da düz metin kullan. Başlık birden fazla talebe uyuyorsa sunucu Id ister.
|
||||
- Düz metin de aynı yoldan geçer: sunucu talimatları modeli `start_dev_request`'e yönlendirir,
|
||||
durum şartı yine sunucuda uygulanır.
|
||||
| `list_components` / `get_component` / `save_component` / `delete_component` | Custom component'ler `ICustomComponentAppService` üzerinden; seed senkronu ve `DataSources` çözümü aynen çalışır. `save_component` ada göre ekler/günceller, tasarımcı belgesi (`Props.visualDesigner`, `sourceMode ≠ code`) taşıyan bileşene kod yazmayı reddeder — kod belgeden üretildiği için tasarımcıdaki ilk kayıtta ezilirdi. |
|
||||
|
||||
**Yetki modeli: MCP yetki vermez.** Kullanıcı MCP'de uygulamadaki yetkisini taşır; MCP'nin iki
|
||||
yetkisi yalnızca kapıdır. Bir çağrı üç katmandan geçer ve her katman ayrı reddeder:
|
||||
|
|
@ -1471,7 +1482,7 @@ yetkisi yalnızca kapıdır. Bir çağrı üç katmandan geçer ve her katman ay
|
|||
| Yetki | Kim alabilir | Ne açar | Açmadığı / sınırı |
|
||||
| --- | --- | --- | --- |
|
||||
| `App.DeveloperKit.McpServers` | Host, kiracı | MCP Servers ekranını görme (`.Create/.Update/.Delete/.Export/.Import` ekran işlemleri) | `/mcp` ucuna erişim vermez |
|
||||
| `App.DeveloperKit.McpServers.Invoke` | Host, kiracı | `/mcp` bağlantısı ve bütün okuma araçları: `server_info`, `list_lists`, `describe_list`, `search_schema`, `query_list`; host'ta ayrıca `get_dev_guide`, `list_wizards`, `get_wizard`, `verify_wizard`, `list_components`, `get_component` | Hiçbir şey yazmaz. Okuma da ekran yetkisine bağlıdır: `R` yetkisi olmayan liste görünmez, sorgulanamaz. Ham SQL (`run_select`, `list_queries`, `run_query`) ayrıca `App.SqlQueryManager` ister |
|
||||
| `App.DeveloperKit.McpServers.Invoke` | Host, kiracı | `/mcp` bağlantısı ve bütün okuma araçları: `server_info`, `list_lists`, `describe_list`, `search_schema`, `query_list`; host'ta ayrıca `get_dev_guide`, `list_wizards`, `get_wizard`, `verify_wizard`, `get_dev_request`, `list_components`, `get_component` | Hiçbir şey yazmaz. Okuma da ekran yetkisine bağlıdır: `R` yetkisi olmayan liste görünmez, sorgulanamaz. Ham SQL (`run_select`, `list_queries`, `run_query`) ayrıca `App.SqlQueryManager` ister |
|
||||
| `App.DeveloperKit.McpServers.Write` | Host, kiracı | MCP üzerinden her değişiklik. **Kiracıda:** `insert_row`, `update_row`, `delete_row`. **Host'ta:** bunlara ek olarak `create_table`, `deploy_wizard`, `delete_wizard`, `save_component`, `delete_component`, `start_dev_request`, `save_dev_request_analysis`, `append_dev_request_note`, `add_dev_request_subtasks` | Kendi başına bir şey yazdırmaz: satır araçları ekranın `C`/`U`/`D` yetkisini, geliştirme araçları Wizard / Custom Components / SQL Query Manager / `App.DevRequests.Update` yetkisini ayrıca ister. Kiracıda geliştirme araçlarını **açmaz** — kiracı bağlamında bu araçlar yetkiden bağımsız kapalıdır (`McpToolNames.TenantTools`). `Invoke` olmadan işe yaramaz |
|
||||
|
||||
**Araç → gereken yetkiler** (Invoke hepsinde aranır, tabloda tekrar yazılmadı)
|
||||
|
|
@ -1960,7 +1971,7 @@ configs/seeds/
|
|||
│ │ # Abp.Identity.Permission{Groups,s}.json — yetki tanımları
|
||||
│ │ # App.Definitions.{CountryGroup,Country,City,District}.json — adres zinciri
|
||||
│ │ # App.Definitions.{Currency,ContactTitle,AiBot}.json — para birimi, hitap, AI bot
|
||||
│ │ # App.Notifications.Notification{Types,Rules}.json — bildirim tipi → kuralı
|
||||
│ │ # App.Notifications.Notification{Templates,Types,Rules}.json — bildirim şablonu, tipi → kuralı
|
||||
│ │ # App.Languages.{Language,LanguageText}.json — dil → metin (eksik LanguageKey metinle üretilir)
|
||||
│ │ # App.SettingDefinitions.json, App.BackgroundWorkers.RecurringJobs.json — ayar tanımları, zamanlanmış işler
|
||||
│ ├── sql/{object,execute}/ # .sql (SQL Server)
|
||||
|
|
@ -1970,8 +1981,9 @@ configs/seeds/
|
|||
```
|
||||
|
||||
> Bu dosyalar elle de düzenlenebilir; ilgili ekrandan tekrar kaydedildiğinde yeniden üretilirler.
|
||||
> Wizard dosyası `EditFileName` ile güncellenirse sunucu önce eski dosyayı ve ürettiği kayıtları
|
||||
> siler, sonra yenisini üretir. Wizard'ın ürettiği ekran **ListForm detayından** düzenlendiğinde
|
||||
> Wizard dosyası `EditFileName` ile güncellenirse deploy veritabanına dokunmaz: dosyalar cevaptan
|
||||
> yeniden yazılır (ad değiştiyse eski dosya silinir), önceki sürümün kayıtları `Pending.Replaced`'a
|
||||
> alınır ve DB Migrate onları kaldırıp ekranı yeniden kurar (`lowcode.instructions.md` §4.0). Wizard'ın ürettiği ekran **ListForm detayından** düzenlendiğinde
|
||||
> de aynı dosya güncellenir (`WizardSeedSynchronizer`): `ListForm`/`Fields` bölümleri ve
|
||||
> `Wizard` bölümündeki karşılıkları veritabanındaki güncel haliyle değiştirilir.
|
||||
|
||||
|
|
|
|||
|
|
@ -448,6 +448,7 @@ public class McpDevelopAppService(
|
|||
var devRequest = await FindDevRequestAsync(request);
|
||||
devRequest.Analysis = string.Concat(devRequest.Analysis, html.Trim());
|
||||
await devRequestRepository.UpdateAsync(devRequest, autoSave: true);
|
||||
await timesheetRecorder.RecordAsync(McpTimesheetTexts.AppendNote);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -497,6 +498,7 @@ public class McpDevelopAppService(
|
|||
|
||||
devRequest.SubTasks = subTasks.ToJsonString();
|
||||
await devRequestRepository.UpdateAsync(devRequest, autoSave: true);
|
||||
await timesheetRecorder.RecordAsync(McpTimesheetTexts.AddSubTasks, items.Count);
|
||||
}
|
||||
|
||||
private static McpDevRequestDto ToDto(DevRequest devRequest)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ public static class McpTimesheetTexts
|
|||
private const string Prefix = "App.Mcp.Timesheet.";
|
||||
|
||||
public const string Analysis = Prefix + "Analysis";
|
||||
public const string AppendNote = Prefix + "AppendNote";
|
||||
public const string AddSubTasks = Prefix + "AddSubTasks";
|
||||
public const string CreateTable = Prefix + "CreateTable";
|
||||
public const string DeployWizard = Prefix + "DeployWizard";
|
||||
public const string DeleteWizard = Prefix + "DeleteWizard";
|
||||
|
|
|
|||
|
|
@ -80,71 +80,57 @@ public static class EditorOptions
|
|||
/// <remarks>
|
||||
/// <c>height</c> verilirse editor sabitlenir ve icerik kaydirilir; <c>min-height</c> ise
|
||||
/// en az yuksekligi korurken yeni satirlarla buyumesine izin verir.
|
||||
/// Bloklar UI'daki <c>htmlEditorOptions.ts</c> varsayilaniyla birebir aynidir: istemci ic ice
|
||||
/// bloklari tek seviye birlestirdigi icin buradaki <c>toolbar</c> varsayilanin yerine gecer.
|
||||
/// </remarks>
|
||||
public static EditorOptionsBuilder Html(int minHeight = 200)
|
||||
=> New()
|
||||
.Raw("mediaResizing", "{\"enabled\":true}")
|
||||
.Raw("imageUpload", "{\"tabs\":[\"file\",\"url\"],\"fileUploadMode\":\"base64\"}")
|
||||
.Raw("toolbar", "{\"multiline\":true,\"items\":[" + string.Join(",", HtmlToolbarItems()) + "]}")
|
||||
.Raw("imageUpload", "{\"tabs\":[\"file\",\"url\"],\"fileUploadMode\":\"base64\"}")
|
||||
.Raw("mediaResizing", "{\"enabled\":true}")
|
||||
.Raw("tableResizing", "{\"enabled\":true}")
|
||||
.Raw("tableContextMenu", "{\"enabled\":true}")
|
||||
.Flag("encodeHtml", true)
|
||||
.Raw("elementAttr", "{\"style\":\"min-height:" + EditorJson.Number(minHeight) + "px\"}");
|
||||
|
||||
private static IEnumerable<string> HtmlToolbarItems()
|
||||
{
|
||||
var fontSizes = new[] { "8pt", "10pt", "12pt", "14pt", "18pt", "24pt", "36pt" };
|
||||
var fontFamilies = new[]
|
||||
{
|
||||
"Arial", "Courier New", "Georgia", "Impact",
|
||||
"Lucida Console", "Tahoma", "Times New Roman", "Verdana"
|
||||
};
|
||||
private static readonly string[] HtmlToolbarNames =
|
||||
[
|
||||
"undo", "redo", "separator",
|
||||
"header", "size", "font", "separator",
|
||||
"bold", "italic", "underline", "strike", "superscript", "subscript", "separator",
|
||||
"color", "background", "separator",
|
||||
"alignLeft", "alignCenter", "alignRight", "alignJustify", "separator",
|
||||
"orderedList", "bulletList", "decreaseIndent", "increaseIndent", "separator",
|
||||
"blockquote", "codeBlock", "link", "image", "separator",
|
||||
"insertTable", "insertHeaderRow", "insertRowAbove", "insertRowBelow", "deleteRow",
|
||||
"insertColumnLeft", "insertColumnRight", "deleteColumn", "cellProperties", "tableProperties", "deleteTable",
|
||||
"separator", "clear"
|
||||
];
|
||||
|
||||
yield return Item("undo");
|
||||
yield return Item("redo");
|
||||
yield return Item("separator");
|
||||
yield return Picker("size", fontSizes, "Font size");
|
||||
yield return Picker("font", fontFamilies, "Font family");
|
||||
yield return Item("separator");
|
||||
yield return Item("bold");
|
||||
yield return Item("italic");
|
||||
yield return Item("strike");
|
||||
yield return Item("underline");
|
||||
yield return Item("separator");
|
||||
yield return Item("alignLeft");
|
||||
yield return Item("alignCenter");
|
||||
yield return Item("alignRight");
|
||||
yield return Item("alignJustify");
|
||||
yield return Item("separator");
|
||||
yield return Item("orderedList");
|
||||
yield return Item("bulletList");
|
||||
yield return Item("separator");
|
||||
yield return "{\"name\":\"header\",\"acceptedValues\":[false,1,2,3,4,5]}";
|
||||
yield return Item("separator");
|
||||
yield return Item("color");
|
||||
yield return Item("background");
|
||||
yield return Item("separator");
|
||||
yield return Item("link");
|
||||
yield return Item("image");
|
||||
yield return Item("separator");
|
||||
yield return Item("clear");
|
||||
yield return Item("codeBlock");
|
||||
yield return Item("blockquote");
|
||||
yield return Item("separator");
|
||||
yield return Item("insertTable");
|
||||
yield return Item("deleteTable");
|
||||
yield return Item("insertRowAbove");
|
||||
yield return Item("insertRowBelow");
|
||||
yield return Item("deleteRow");
|
||||
yield return Item("insertColumnLeft");
|
||||
yield return Item("insertColumnRight");
|
||||
yield return Item("deleteColumn");
|
||||
yield return Item("cellProperties");
|
||||
yield return Item("tableProperties");
|
||||
}
|
||||
private static readonly string[] HtmlFontSizes = ["8pt", "10pt", "12pt", "14pt", "18pt", "24pt", "36pt"];
|
||||
|
||||
private static readonly string[] HtmlFontFamilies =
|
||||
[
|
||||
"Arial", "Courier New", "Georgia", "Impact",
|
||||
"Lucida Console", "Segoe UI", "Tahoma", "Times New Roman", "Verdana"
|
||||
];
|
||||
|
||||
private static readonly string[] HtmlHeaderValues = ["false", "1", "2", "3", "4", "5", "6"];
|
||||
|
||||
private static IEnumerable<string> HtmlToolbarItems()
|
||||
=> HtmlToolbarNames.Select(name => name switch
|
||||
{
|
||||
"size" => Picker(name, HtmlFontSizes.Select(EditorJson.Quote), "Font size"),
|
||||
"font" => Picker(name, HtmlFontFamilies.Select(EditorJson.Quote), "Font family"),
|
||||
"header" => Picker(name, HtmlHeaderValues, "Header"),
|
||||
_ => Item(name)
|
||||
});
|
||||
|
||||
private static string Item(string name) => "{\"name\":" + EditorJson.Quote(name) + "}";
|
||||
|
||||
/// <summary><paramref name="values"/> JSON olarak yazilmis degerlerdir (metin tirnakli, sayi/bool ciplak).</summary>
|
||||
private static string Picker(string name, IEnumerable<string> values, string ariaLabel)
|
||||
=> "{\"name\":" + EditorJson.Quote(name) +
|
||||
",\"acceptedValues\":[" + string.Join(",", values.Select(EditorJson.Quote)) + "]" +
|
||||
",\"acceptedValues\":[" + string.Join(",", values) + "]" +
|
||||
",\"options\":{\"inputAttr\":{\"aria-label\":" + EditorJson.Quote(ariaLabel) + "}}}";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.PermissionManagement;
|
||||
|
|
@ -49,20 +48,5 @@ public static class AbpPermissionsExtensions
|
|||
.Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Yetki ekranindaki sira (<see cref="PlatformConsts.Permissions.Order"/>) kardesler arasindadir;
|
||||
/// yeni kayit en buyuk kardes sirasinin bir fazlasini alir, kardes yoksa 1. Bos birakilan sira
|
||||
/// 0 olur ve kayit listenin en ustune cikar.
|
||||
/// </summary>
|
||||
public static int NextPermissionOrder(this IEnumerable<IHasExtraProperties> siblings)
|
||||
{
|
||||
return siblings.Select(s => s.GetProperty<int>(PlatformConsts.Permissions.Order)).DefaultIfEmpty(0).Max() + 1;
|
||||
}
|
||||
|
||||
public static void SetPermissionOrder(this IHasExtraProperties record, int order)
|
||||
{
|
||||
record.SetProperty(PlatformConsts.Permissions.Order, order);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
19
claude.md
19
claude.md
|
|
@ -176,14 +176,19 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
- **`scriptRecipes.ts` (TS) ↔ `Domain.Shared/Editors/*.cs`** — biri değişirse diğeri de değişir.
|
||||
İkisinin çıktısı **birebir aynı** olmak zorundadır; aksi hâlde seeder ile basılan script
|
||||
dialogda "elle düzenlenmiş" sayılır ve kural editörü kapanır.
|
||||
- **`htmlEditorOptions.ts` ↔ `EditorOptions.Html`** — HtmlEditor varsayılanı iki yerde yazılır ve
|
||||
bloklar birebir aynıdır. İstemci iç içe blokları tek seviye birleştirdiği için seed edilen
|
||||
`toolbar` varsayılanın yerine geçer; biri değişip diğeri değişmezse seed'li ekranlar eski araç
|
||||
çubuğunu gösterir.
|
||||
- **Wizard seed dosyasında tekrar yok** → `Wizard` bölümü yalnızca ekrandan üretilemeyen bilgileri
|
||||
taşır. `ListForm`/`Fields` içinde karşılığı olan her alan (veri kaynağı, select, anahtar alan,
|
||||
kırılım/düzen/düzenleme bayrakları, görünüm option blokları, alt form, widget, iş akışı, alan
|
||||
tanımları) dosyaya yazılmadan çıkarılır (`WizardSeedFileDto.ToSeedJson`) ve okurken geri
|
||||
doldurulur (`FromSeedJson`). Wizard'a yeni bir alan eklerken karşılığı ListForm'da varsa listeye ekle.
|
||||
Dosyada kalan wizard alanları üç başlık altında toplanır — `Menu`, `Language`, `Groups` — ve
|
||||
`ListFormCode` → `WizardCode`, `MenuParentModuleId` → `ModuleId` adıyla yazılır; varsayılanı olan
|
||||
alanlar (`CreateMenu: true`, boş `DataSourceConnectionString`) hiç yazılmaz. Bu yalnızca dosya biçimidir; C#
|
||||
`ListFormCode` → `WizardCode`, `MenuParentModuleId` → `ModuleId`, `LanguageTexts` → `Language.Texts`
|
||||
adıyla yazılır; varsayılanı olan alanlar (`CreateMenu: true`, boş `DataSourceConnectionString`, boş
|
||||
`MenuParentPath` / `LanguageTexts`) hiç yazılmaz. Bu yalnızca dosya biçimidir; C#
|
||||
sözleşmesi düzdür, dönüşüm `WizardSeedFileDto.ToSeedJson` / `FromSeedJson` içindedir. **Wizard
|
||||
seed dosyası her zaman bu iki metotla okunup yazılır**; düz `JsonSerializer` çağrısı bloklu
|
||||
bölümleri sessizce düşürür.
|
||||
|
|
@ -264,8 +269,10 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
`add_dev_request_subtasks` ile yazılır: atanan kişi bağlanan kullanıcı, bitiş tarihi bugün —
|
||||
sunucu doldurur, modele bırakılmaz. `Timesheets`'i tamamen sunucu yazar
|
||||
(`IMcpDevRequestTimesheetRecorder`): `get_dev_request`/`start_dev_request` talebi etkin talep yapar,
|
||||
sonraki her MCP yazma işlemi ona `App.Mcp.Timesheet.*` anahtarından Türkçe açıklama ve ölçülen
|
||||
süreyle bir satır ekler. Yeni bir MCP yazma aracı eklenirse kaydedici çağrısı ve dil anahtarı da eklenir.
|
||||
sonraki her üretim/veri yazma işlemi (`create_table`, `deploy_wizard`, `delete_wizard`,
|
||||
`save_component`, `delete_component`, satır araçları, `save_dev_request_analysis`,
|
||||
`append_dev_request_note`, `add_dev_request_subtasks`) ona `App.Mcp.Timesheet.*` anahtarından Türkçe
|
||||
açıklama ve ölçülen süreyle bir satır ekler; yalnızca talebi açan `start_dev_request` satır yazmaz. Yeni bir üretim/veri yazma aracı eklenirse kaydedici çağrısı ve dil anahtarı da eklenir.
|
||||
- **Talep analizi** → `Description` talebin yazıldığı hâliyle kalır; MCP ona yazmaz. Analiz ve
|
||||
üretim notları `Analysis` kolonundadır (Todo panosunda `AnalysisExpr`, Açıklama yanında sekme).
|
||||
Durum sırası `Backlog → Analysis → Ready to Start → …`: "Analiz et" `save_dev_request_analysis`
|
||||
|
|
@ -289,8 +296,8 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
karşılık gelen yetkiyle eklenir. `create_table` bu yüzden `.Write`'a ek olarak `App.SqlQueryManager`
|
||||
ister; tablo scriptini tasarımcının `generateCreateTableSql` çıktısıyla aynı biçimde üretir
|
||||
(`McpTableCreator`) — tasarımcının şablon kolonları ya da script biçimi değişirse o da değişir.
|
||||
- **Bildirim kapsamı** → bildirim tipi, kuralı ve kuyruğu kiracıya aittir (`Adm_T_NotificationType`,
|
||||
`Adm_T_NotificationRule`, `Adm_T_Notification`; üçü de `IMultiTenant`) ve ekranların tamamı
|
||||
- **Bildirim kapsamı** → bildirim tipi, kuralı ve kuyruğu kiracıya aittir (`Adm_T_NotificationTemplate`,
|
||||
`Adm_T_NotificationType`, `Adm_T_NotificationRule`, `Adm_T_Notification`; dördü de `IMultiTenant`) ve ekranların tamamı
|
||||
Administration › Bildirimler altındadır. Ayrı bir manuel gönderim tablosu yoktur: **Bildirimler**
|
||||
ekranının ekleme formu elle gönderimdir, uç alıcı × kanal açılımını kuyruğa yazar
|
||||
(`list-form-dynamic-api/notification-insert`). Yeni kiracıya varsayılan tür/kural kümesi
|
||||
|
|
|
|||
|
|
@ -67428,6 +67428,34 @@
|
|||
"Key": "App.Mcp.Timesheet.DeleteRow",
|
||||
"Value": "{0} ekranından satır silindi"
|
||||
},
|
||||
{
|
||||
"Id": "02d139fc-753d-567a-b672-8aa0a0212ad0",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Mcp.Timesheet.AppendNote",
|
||||
"Value": "Production note added to the analysis"
|
||||
},
|
||||
{
|
||||
"Id": "9e9cc3eb-557b-5a02-8730-29347f4f77b4",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Mcp.Timesheet.AppendNote",
|
||||
"Value": "Analize üretim notu eklendi"
|
||||
},
|
||||
{
|
||||
"Id": "eb67cbd2-c6b3-57d6-ab44-ee7e79636553",
|
||||
"CultureName": "en",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Mcp.Timesheet.AddSubTasks",
|
||||
"Value": "{0} completed subtasks added"
|
||||
},
|
||||
{
|
||||
"Id": "ec94c375-713b-51f8-8db8-5e58b9e4ce7b",
|
||||
"CultureName": "tr",
|
||||
"ResourceName": "Platform",
|
||||
"Key": "App.Mcp.Timesheet.AddSubTasks",
|
||||
"Value": "{0} tamamlanmış alt görev eklendi"
|
||||
},
|
||||
{
|
||||
"Id": "a5e491f7-a85c-572f-bf66-4245cb84fa36",
|
||||
"CultureName": "en",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* `<HtmlEditor {...htmlEditorDefaults}>` ile, dinamik formlar `mergeHtmlEditorOptions` ile
|
||||
* aynı yetenek setini alır; ListForm'daki "HTML toolbar" kalıbı da buradan beslenir.
|
||||
* Değerler JSON'a yazılabilir kalmalıdır — kalıp editorOptions kolonuna olduğu gibi kaydedilir.
|
||||
* Seed'li ekranlar aynı blokları C# `EditorOptions.Html` ile yazar; biri değişirse diğeri de değişir.
|
||||
*/
|
||||
import type { Properties as HtmlEditorProperties } from 'devextreme/ui/html_editor'
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue