diff --git a/.github/instructions/ai.instructions.md b/.github/instructions/ai.instructions.md index 820e270c..e67f3d02 100644 --- a/.github/instructions/ai.instructions.md +++ b/.github/instructions/ai.instructions.md @@ -294,7 +294,7 @@ the Wizard's `Custom` path. per-command Form permissions (`selectPermission`, `insertPermission`, `updatePermission`, `deletePermission`). In `Otomatik` mode the base is the read permission the Wizard created for the component and the commands get `''` / `.Create` / `.Update` / `.Delete` suffixes. -- List screen permissions: `App.DeveloperKit.CustomComponents{,.Create,.Update,.Delete}`. +- List screen permissions: `App.DeveloperKit.CustomComponents{,.Create,.Update,.Delete,.Export,.Import}`. - Every save/delete is mirrored into `configs/seeds/{scope}/data/App.DeveloperKit.CustomComponents.json`; the endpoints it uses are referenced through `crud/{Entity}.json`. A component that is not seed-backed is not done. @@ -657,10 +657,12 @@ a deploy. AI must learn and teach implementation flow primarily from these asset - LanguagesData.json - WizardDataSeeder.cs / CrudDataSeeder.cs — the seeders that read surface B below +- ListFormSeedDataApplier (Domain/Data/) — applies `data/{ListFormCode}.json` after every + contributor has run **B. Runtime seeds (written by the running application)** — `configs/seeds/`, resolved through -`SeedPathResolver`. The Wizard, the Custom Components screen / Visual Designer and the CRUD -Endpoint Manager write here; the +`SeedPathResolver`. The Wizard, the Custom Components screen / Visual Designer, the CRUD +Endpoint Manager and every ListForm screen with a `SeedFilePath` write here; the seeders above restore them when the database is recreated. Scope folders mirror the CDN layout: ``` diff --git a/.github/instructions/lowcode.instructions.md b/.github/instructions/lowcode.instructions.md index 50b2c81c..fe9ac9bc 100644 --- a/.github/instructions/lowcode.instructions.md +++ b/.github/instructions/lowcode.instructions.md @@ -1490,6 +1490,9 @@ Kurallar: - `AuthName` boş bırakılırsa buton **herkese görünür**. Süreç butonlarında bu alanı boş bırakma: yetki kontrolünden geçmeyen buton hiç çizilmez, gizlemenin tek doğru yolu budur. - `Text` ve `Hint` dil anahtarıdır; çeviri `::` öneki eklenerek çözülür. Düz metin yazma. +- `Icon` bir **DevExtreme ikon adıdır** (`check`, `trash`, `doc`, `preferences` …); tema CSS'i + `dx-icon-` sınıfıyla çizer. Komut diyalogundaki alan hazır ikon listesini önerir, listede + olmayan bir ad da yazılabilir. Form ekranının araç çubuğu da aynı ikon adlarını kullanır. - Toolbar butonu **seçili satırlarla** çalışır; `SelectionJson` uygun modda (`single`/`multiple`) olmalıdır. İş akışı varsa wizard bunu zaten `single` yapar. - Satır bazlı aksiyon istiyorsan `ButtonPosition: 0` kullan; buton komut sütununda görünür. @@ -2356,7 +2359,7 @@ Form düğümünün `id`'si) ve Save/Delete üzerinden geri yazar. Olaylar: `onL - `Özel` mod: yetki adı elle yazılır. - Boş bırakılan komut serbesttir. -Liste ekranı yetkileri: `App.DeveloperKit.CustomComponents{,.Create,.Update,.Delete}`. +Liste ekranı yetkileri: `App.DeveloperKit.CustomComponents{,.Create,.Update,.Delete,.Export,.Import}`. ### 7.6 Bileşeni menüye bağlama @@ -2892,9 +2895,11 @@ Endpoint **tanımlarını** düzenleme yetkileri ListForm ekranının `App.DeveloperKit.CustomEndpoints{,.Create,.Update,.Delete}` yetkileridir — çağırma yetkilerinden (`.Get/.Post/.Put/.Remove` + `PermissionsJson`) ayrıdır. -**Seed:** ekrandan girilen kayıt yalnızca veritabanında yaşar. Proje teslimi için kaydı -`sql/execute/{Ad}.sql` upsert prosedürüyle geri getirilebilir yap (§9.14 uyarısı); platform -varsayılanı ise çekirdeğin `Seeds/TenantData.json` → `CustomEndpoints` bloğundadır. +**Seed:** platform varsayılanları `configs/seeds/{kapsam}/data/App.DeveloperKit.CustomEndpoints.json` +dosyasından gelir; ekranın `SeedSyncInsert/Update/Delete` bayrakları **kapalıdır**, yani ekrandan +girilen kayıt dosyaya yansımaz ve yalnızca veritabanında yaşar. Proje teslimi için kaydı ya bu +dosyaya elle ekle ya da `sql/execute/{Ad}.sql` upsert prosedürüyle geri getirilebilir yap +(§9.14 uyarısı). **Ne zaman CRUD, ne zaman Custom Endpoint?** Tek tabloya standart CRUD gerekiyorsa CRUD Endpoint (otomatik üretilir, `crud/{Entity}.json` ile seed'lenir, filtre sözleşmesi hazırdır). diff --git a/README.md b/README.md index 6e077e18..08ea13db 100644 --- a/README.md +++ b/README.md @@ -632,8 +632,8 @@ Teknik kullanıcılar için `/admin/developerkit` altında toplanan araçlar: | **Custom Endpoint** | `/admin/list/App.DeveloperKit.CustomEndpoints` | SQL veya servis tanımından REST endpoint üretimi; GET/POST/PUT/DELETE için ayrı yetki kapıları (`App.DeveloperKit.CustomEndpoints.*`) ve kullanıcı/rol/global erişim kuralları. | | **CRUD Endpoint** | SQL Query Manager içinde | Tablo tanımından tam CRUD endpoint kümesi üretimi. Ayrı ekranı yoktur; bkz. aşağıdaki not. | | **Dynamic Service** | `/admin/list/App.DeveloperKit.DynamicServices` | Liste bir ListForm ekranıdır (KPI şeridi, Swagger butonu, kart/ızgara görünümü); kod yazma listeden açılan `DynamicServiceEditor` diyalogundadır: Monaco editörü, Roslyn ile derleme (`TestCompile`), yayınlama (`Publish`) ve çalışan uygulamaya controller olarak kaydetme. Yetkiler: Create/Edit/Delete/Manage/TestCompile/Publish/ViewCode. | -| **Custom Component** | `/admin/list/App.DeveloperKit.CustomComponents` | React bileşenini veritabanında saklama; `@babel/standalone` ile tarayıcıda derleyip route'a bağlama. Liste bir ListForm ekranıdır (KPI şeridi, ızgara/kart görünümü, grid'in kendi ekleme/düzenleme formu); satırdaki **Design** butonu `/admin/developerkit/components/design/{id}` tasarımcısını, **Open URL** butonu bileşenin `RoutePath`'ini açar. Kayıtlar `configs/seeds/host/data/App.DeveloperKit.CustomComponents.json` dosyasına senkronlanır. Yetkiler `App.DeveloperKit.CustomComponents{,.Create,.Update,.Delete}`. | -| **Visual Designer** | Component editörü içinde | Sürükle-bırak kanvas ile bileşen üretimi ve kod üretimi (`visualDesigner/codeGenerator.ts`). | +| **Custom Component** | `/admin/list/App.DeveloperKit.CustomComponents` | React bileşenini veritabanında saklama; `@babel/standalone` ile tarayıcıda derleyip route'a bağlama. Liste bir ListForm ekranıdır (KPI şeridi, ızgara/kart görünümü, grid'in kendi ekleme/düzenleme formu); satırdaki **Design** butonu `/admin/developerkit/components/design/{id}` tasarımcısını, **Open URL** butonu bileşenin `RoutePath`'ini açar. Kayıtlar `configs/seeds/host/data/App.DeveloperKit.CustomComponents.json` dosyasına senkronlanır. Yetkiler `App.DeveloperKit.CustomComponents{,.Create,.Update,.Delete,.Export,.Import}`. | +| **Visual Designer** | `/admin/developerkit/components/design/:id` | Custom Component listesindeki **Design** butonundan açılır; sürükle-bırak kanvas ile bileşen üretimi ve kod üretimi (`visualDesigner/codeGenerator.ts`). | | **ListForm** | `/admin/list/App.Listforms.Listform` | Var olan ekranların ham tanım listesi; buradan `/admin/listform/edit/{kod}` sekmeli editörüne geçilir. | | **Wizard Manager** | `/admin/listform/wizardManager` | Üretilmiş wizard seed dosyalarının listesi/kartı, düzenleme, silme, DB migrate, export/import. Yetki `App.Listforms.Wizard{,.Create,.Update,.Delete,.Export,.Import}`. | @@ -783,7 +783,7 @@ içindedir; oradaki kontroller yalnızca butonları gizler, asıl kontrol AppSer | Grup | Alt yetkiler | | --- | --- | | `App.Listforms.Wizard` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import` | -| `App.DeveloperKit.CustomComponents` | `.Create`, `.Update`, `.Delete` | +| `App.DeveloperKit.CustomComponents` | `.Create`, `.Update`, `.Delete`, `.Export`, `.Import` | | `App.DeveloperKit.CustomEndpoints` | `.Get`, `.Post`, `.Put`, `.Remove` (dispatcher üzerinden çağrı kapısı; endpoint bazlı User/Role/Global kuralları bunun üstünde denetlenir) | | `App.DeveloperKit.DynamicServices` | `.Create`, `.Edit`, `.Delete`, `.Manage`, `.TestCompile`, `.Publish`, `.ViewCode` | | `App.SqlQueryManager` | `.CrudEndpoints` | @@ -1197,9 +1197,12 @@ derlenip yayınlanır. Yeni bir modülün nasıl kurulacağını öğrenmek içi - `LanguagesData.json` — dil anahtarları (EN/TR) - `WizardDataSeeder.cs`, `CrudDataSeeder.cs` — aşağıdaki runtime seed dosyalarını okuyup uygulayan seeder'lar +- `ListFormSeedDataApplier` (`Domain/Data/`) — bütün contributor'lar bittikten sonra + `data/{ListFormCode}.json` dosyalarını uygular **2. Runtime'da üretilen seed'ler** — `configs/seeds/`. Wizard, Custom Components ekranı/Visual -Designer ve CRUD Endpoint Manager çalışma zamanında burayı yazar; veritabanı silinip yeniden oluşturulduğunda aynı dosyalar +Designer, CRUD Endpoint Manager ve `SeedFilePath` tanımlı ListForm ekranları çalışma zamanında +burayı yazar; veritabanı silinip yeniden oluşturulduğunda aynı dosyalar geri yüklenir. Kapsam klasörü CDN düzeniyle aynıdır ve `SeedPathResolver` üzerinden çözülür: ``` @@ -1207,6 +1210,7 @@ configs/seeds/ ├── host/ # host kapsamı │ ├── wizard/ # {Ad}.json → WizardDataSeeder │ ├── crud/ # {EntityName}.json → CrudDataSeeder +│ ├── data/ # {ListFormCode}.json → ListFormSeedDataApplier │ ├── sql/{object,execute}/ # .sql (SQL Server) │ └── postgres/{object,execute}/ ├── tenants/{tenantId}/… # aynı düzen, tenant kapsamı diff --git a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogCommand.tsx b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogCommand.tsx index 94e934d4..f6e8bd75 100644 --- a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogCommand.tsx +++ b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogCommand.tsx @@ -18,9 +18,10 @@ import { SelectBoxOption } from '@/types/shared' import { useStoreActions, useStoreState } from '@/store' import { useLocalization } from '@/utils/hooks/useLocalization' import { Field, FieldProps, Form, Formik } from 'formik' +import CreatableSelect from 'react-select/creatable' import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { number, object, string } from 'yup' -import { commandButtonPositionTypeOptions, urlOptions } from '../options' +import { commandButtonIconOptions, commandButtonPositionTypeOptions, urlOptions } from '../options' import { JsonRowDialogData } from './types' import { deleteListFormJsonRow, @@ -248,13 +249,34 @@ function JsonRowOpDialogCommand({ invalid={errors.icon && touched.icon} errorMessage={errors.icon} > - + + {({ field, form }: FieldProps) => ( +