Veri Alışverişi (DataExchange)
Şirket genelinde ortak olan içe/dışa aktarma standardının önyüz tarafı. Grid'e bir process key verirsiniz; kolon şemasını, zorunlu alanları, lookup eşlemelerini ve doğrulama kurallarını sunucu bildirir. Livalib bu sözleşmeyi okuyup şablon indirme, doğrulama, kolon eşleştirme, önizleme ve içe aktarma adımlarını kendisi yürütür — sayfada elle Excel ayrıştırma kodu kalmaz. Kullanıcının Excel'i şablondan farklı olsa bile kolonlar sihirbazda sistem alanlarına bağlanır; kurulan eşleme kullanıcıya özel bir profil olarak saklanabilir.
import {
LivaGridConfigProvider,
LivaImportWizard,
useDataExchange,
useContract,
createColumnMappingProfileApiStorage,
type DataExchangeContract,
type ColumnMappingProfileStorage,
} from "@dataliva/livalib";
Kurulum — LivaGridConfigProvider
Uygulama kökünde bir kez sarmalayın. Modülün tüm HTTP çağrıları buradaki
yapılandırmayı kullanır: token Authorization: Bearer …, lang ise
Accept-Language başlığına yazılır.
<LivaGridConfigProvider
dataExchange={{
baseUrl: `${API_URL}/data-exchange`,
showDiagnostics: isSysAdmin,
mappingProfilesUrl: `${API_URL}/UserImportProfile`,
}}
token={() => getToken()}
lang="TR"
>
<App />
</LivaGridConfigProvider>
| Alan | Tip | Açıklama |
|---|---|---|
dataExchange.baseUrl | string | Uç nokta kökü. Varsayılan /api/data-exchange. |
dataExchange.endpointsResolver | (processKey) => DataExchangeEndpoints | Rota şeması standarda uymuyorsa altı uç noktayı elle üretin. |
dataExchange.headerPolicy | 'tech-suffix' | 'header-only' | Şablon başlıklarında teknik alan adının gösterilip gösterilmeyeceği. |
dataExchange.showDiagnostics | boolean | Sihirbazda teknik bilgileri gösterir (aşağıda Teknik bilgiler). Varsayılan false. |
dataExchange.mappingProfilesUrl | string | Kullanıcı bazlı eşleştirme profillerinin REST tabanı (aşağıda Eşleştirme profilleri). |
dataExchange.mappingProfileStorage | ColumnMappingProfileStorage | REST yerine özel profil deposu; mappingProfilesUrl'den önceliklidir. |
token | string | (() => string | undefined) | Fonksiyon verin; token yenilendiğinde provider'ı yeniden render etmeye gerek kalmaz. |
lang | string | Accept-Language başlığı (ör. "TR"). |
fetch | typeof fetch | Test veya interceptor için fetch değişimi. |
mappingProfilesUrl ve mappingProfileStorage ikisi de verilmezse sihirbazdaki
profil bölümü hiç görünmez; kolon eşleştirme yine çalışır.
baseUrl verildiğinde uç noktalar şu kalıptan türetilir:
| Uç nokta | Rota |
|---|---|
definition | {base}/{processKey}/definition |
template | {base}/{processKey}/template |
export | {base}/{processKey}/export |
import | {base}/{processKey}/import |
validate | {base}/{processKey}/validate |
status | {base}/{processKey}/status |
validate ve import rotalarının sonundaki ek yollar (/validate-rows,
/validate-source, /import-rows, /import-source) bu iki taban üzerinden
otomatik türetilir. Adaptör kataloğu ise {base}/adapters?capability=read
adresinden okunur.
İstekler ve route gövdesi
routeParams URL'ye eklenmez; her istekte gövdedeki route alanında
taşınır. Yıl/şirket gibi kapsam bilgisi ya da uzun bir kimlik listesi
(ör. ccntId=a,b,c,…) query string'e konduğunda IIS maxQueryString sınırını
aşar ve sunucu API'ye hiç ulaşmadan 404 döner — bu yüzden gövde kullanılır.
| Çağrı | İstek |
|---|---|
definition | GET, gövdesiz |
template | POST · { withData, route } |
export | POST · { ...payload, route } |
validate / import | POST · multipart: file + route (JSON metni olarak form alanı) |
validate-rows / import-rows | POST · { rows, route } |
validate-source / import-source | POST · { sourceKind, sourceOptions, route } |
adapters | GET {base}/adapters?capability=read|write |
route bir Record<string, string> nesnesidir: değerler metne çevrilir,
undefined, null ve "" olanlar atılır; geriye bir şey kalmazsa route
alanı hiç gönderilmez. JSON gövdeli isteklere Content-Type: application/json
eklenir, multipart istekte başlığı tarayıcı belirler. Başarısız (2xx dışı) her
yanıt "POST {url} → 404" biçiminde mesajı olan bir Error fırlatır; sihirbaz
bu metni üstteki hata bandında gösterir.
Grid'e bağlama — bildirimsel yol
LivaDataGrid ve LivaTreeList, importExportSettings.processKey verildiğinde
içe aktarma sihirbazını kendiliğinden monte eder. Ayrıca araç çubuğundaki
menü de sözleşmeye göre değişir: Boş Şablon İndir ve Verili Şablon İndir
öğeleri çıkar, eski SQL Export / SQL Import öğeleri gizlenir.
<LivaDataGrid
{...getGridProps()}
keyExpr="id"
columns={kolonlar}
dataSource={ds}
importExportSettings={{
enabled: true,
processKey: "expense-definition",
routeParams: { budgetYear, companyId },
wizardTitle: "Masraf Tanımı İçe Aktarma",
}}
/>
| Alan | Tip | Açıklama |
|---|---|---|
enabled | boolean | Araç çubuğundaki içe/dışa aktarma butonunu açar. |
processKey | string | Sözleşme anahtarı. Verildiğinde sihirbaz devreye girer. |
baseUrl | string | Yalnızca bu grid için kök adres değişimi. |
endpoints | Partial<DataExchangeEndpoints> | Tek tek uç nokta ezme. |
headerPolicy | 'tech-suffix' | 'header-only' | Başlık politikası ezme. |
contract | DataExchangeContract | Sözleşme elde varsa definition isteği atlanır. |
autoProvision | Record<string, boolean> | Eksik kayıtların otomatik oluşturulmasını alan bazında aç/kapat. |
routeParams | Record<string, string | number | boolean | null | undefined> | Tüm isteklerin gövdesinde route olarak gönderilir. |
config | Partial<LivaGridConfig> | Provider yapılandırmasını bu grid için ezer. |
wizardTitle | string | Sihirbaz başlığı. |
closeOnComplete | boolean | Varsayılan false — sihirbaz rapor adımında açık kalır. |
onImportCompleted | (report: DataExchangeReport) => void | İçe aktarma raporu döndüğünde, grid refresh() edildikten sonra çağrılır. |
routeParams'ı eksik bırakmak en sık yapılan hatadır: yıl/şirket gibi bağlam sunucuya gitmezse şablon boş, doğrulama ise "kayıt bulunamadı" hatalarıyla döner.
Aktarım bitince grid kendi refresh()'ini çağırır; bu yalnızca bağlı
dataSource'u yeniden okur. Grid'e yerel bir dizi verdiyseniz yeni kayıtlar
görünmez — veriyi onImportCompleted içinde kendiniz yeniden yükleyin.
LivaTreeList aynı ayar tipini kullanır, ancak sihirbazı aktarım bitince
closeOnComplete'e bakmadan her zaman kapatır.
config sığ birleştirilir: config.dataExchange verdiğinizde uç nokta
çözümünde provider'daki dataExchange nesnesinin tamamının yerine geçer. Bu
durumda baseUrl'i ya config.dataExchange içinde ya da grid'in baseUrl
alanında yeniden verin; aksi halde istekler varsayılan /api/data-exchange
köküne gider.
Eski kancalar (escape hatch)
Standart sihirbazdan çıkmak için onImportExcel verin — bu alan doluyken
sihirbaz devre dışı kalır ve klasik dosya seçici açılır. Aynı şekilde
onExportExcel, onDownloadTemplate, onImportSettings ve onExportSettings
kendi akışınızı bağlamak içindir. Yeni sayfalarda bunlara ihtiyaç olmamalıdır.
İçe aktarma sihirbazı — LivaImportWizard
Grid dışında (ör. bir sayfa butonundan) elle de monte edilebilir:
const [acik, setAcik] = useState(false);
<LivaImportWizard
processKey="expense-definition"
routeParams={{ budgetYear }}
visible={acik}
onHiding={() => setAcik(false)}
onCompleted={(rapor) => {
notifications.show({ title: "İçe aktarma", message: `${rapor.insertedCount} kayıt eklendi` });
gridRef.current?.instance().refresh();
}}
title="Masraf Tanımı İçe Aktarma"
translate={t}
showDiagnostics={isSysAdmin}
/>
| Prop | Tip | Varsayılan |
|---|---|---|
processKey | string | — (zorunlu) |
visible | boolean | — (zorunlu) |
onHiding | () => void | — (zorunlu) |
baseUrl | string | — |
endpoints | Partial<DataExchangeEndpoints> | — |
contract | DataExchangeContract | — (verilirse definition isteği atlanır) |
routeParams | RouteParams | — |
config | Partial<LivaGridConfig> | — |
onCompleted | (report: DataExchangeReport) => void | — |
title | string | "Veri İçe Aktarma" (showDiagnostics açıkken "Veri İçe Aktarma — {processKey}") |
translate | (key: string) => string | — |
showDiagnostics | boolean | config.dataExchange.showDiagnostics → provider ayarı → false |
onCompleted, import-rows isteği bir rapor döndürdüğü anda çağrılır — rapor
satır hataları içerse (errorCount > 0) bile. İstek tümden başarısız olursa
çağrılmaz; hata sihirbazın üstünde gösterilir.
Adımlar
- Kaynak — adaptör kataloğu
capability=readile çekilir. Katalogda tek adaptör varsa kendiliğinden seçilir. Adaptörüntransportdeğeri akışı belirler:multipartdosya yükler,sourceise adaptörün kendi alanlarını (fields) doldurtup sunucudan okur. Önizle düğmesi, adaptörün zorunlu alanları dolunca açılır. - Önizleme —
multipartiçin dosya sunucuyavalidateile gönderilirken aynı anda tarayıcıda da okunur;sourceiçinvalidate-sourceçağrılır. Sözleşmevalidateyanıtındakicontractalanından alınır. İlk görünüm kaynak Excel'in kendisidir (Görünüm: Kaynak Excel): salt okunurdur, sunucunun ilk doğrulamasındaki hata sayısı yalnızca bilgi olarak gösterilir. İleri gitmenin tek yolu Kolon Eşleştirme düğmesidir. - Kolon Eşleştirme — Excel kolonları sözleşmedeki alanlara bağlanır,
Eşlemeyi Uygula ve Devam ile eşlenmiş satırlar
validate-rows'a gider (ayrıntı aşağıda Kolon eşleştirme). Hata yoksa doğrudan Onay'a geçilir. Hata dönerse sihirbaz önizlemeye geri döner; bu kez görünüm Eşlenmiş veridir, hücreler düzenlenebilir, satırlar silinebilir ve hatalı hücreler kırmızı işaretlenir. Düzenlemeden sonra Kontrol Et satırları yenidenvalidate-rowsile doğrular; hata ya da kontrol edilmemiş düzenleme kaldıkça Devam kapalıdır. - Onay — hata kalmadıysa açılır. Planlanan ekleme/güncelleme sayıları
(
plannedInsertCount,plannedUpdateCount) ve toplam satır gösterilir. Başarılı olursa bu pencereyi otomatik kapat kutusu işaretlenirseerrorCount === 0olan aktarımdan sonra sihirbaz kapanır. - Rapor —
DataExchangeReportözeti: eklenen, güncellenen, hatalı ve işlenen satır sayıları, aktarım öncesi/sonrası kayıt sayısı (recordsBefore/recordsAfter) ve varsa satır hataları tablosu.closeOnCompleteverilmedikçe sihirbaz bu adımda açık kalır.
İçe aktarma, kaynak adaptörü ne olursa olsun her zaman
import-rowsüzerinden gönderilir: sunucuya giden, eşlenmiş ve önizlemede düzeltilmiş satırlardır. Sihirbazimportveimport-sourceuçlarını kullanmaz; bunlaruseDataExchangeüzerinden erişilebilir kalır.
validate-rows çağrıları 5000 satırlık parçalar halinde yapılır; parçaların
hataları birleştirilirken rowNumber değerleri kaydırılır, böylece hata satır
numaraları dosyanın tamamına göre kalır.
Teknik bilgiler — showDiagnostics
Açıkken sihirbaz başlığına process key eklenir (title verilmediyse) ve Onay
adımında bir Kaynak kartı çıkar: kullanılan adaptör (dosya adı ya da
adaptörün görünen adı), sözleşmenin eşleşme anahtarı (upsertKey) ve süreç
anahtarı. Son kullanıcıyı ilgilendirmeyen bu bilgileri yalnızca yöneticilere
açmak için provider'da bir kez verin:
<LivaGridConfigProvider dataExchange={{ baseUrl, showDiagnostics: isSysAdmin }}>
Öncelik sırası: showDiagnostics prop'u → config.dataExchange.showDiagnostics
→ provider'daki dataExchange.showDiagnostics → false. Grid'in kendiliğinden
monte ettiği sihirbaz bu prop'u almaz; orada provider ayarı ya da
importExportSettings.config.dataExchange.showDiagnostics geçerlidir.
Kolon eşleştirme
Sihirbazdaki her içe aktarma bu adımdan geçer. Kullanıcının Excel'i şablonla birebir aynı olmak zorunda değildir: kolonları farklı adlandırılmış, farklı sıralanmış ya da fazladan kolon içeren bir dosya da burada sistem alanlarına bağlanır.
Geliştiricinin ayrıca bir şey sağlaması gerekmez — ekranı sözleşmedeki
columns sürer: her kolonun header'ı satır başlığı, required değeri
Zorunlu rozeti, name ve dataType alt bilgi olarak gösterilir; satırlar
order'a göre dizilir.
Kaynak tablo. multipart adaptörlerde dosyanın ilk çalışma sayfası
okunur; ilk satır başlık satırıdır. Başlığı boş kolonlar atlanır, aynı başlık
tekrar ediyorsa sonrakiler Başlık (2), Başlık (3) diye ayrılır, tamamen boş
satırlar atılır. Dosya boşsa, çalışma sayfası ya da başlık satırı yoksa
sihirbaz hata verir; başlık olup veri satırı yoksa Kolon Eşleştirme düğmesi
kapalı kalır. source adaptörlerde kaynak kolonları, validate-source
yanıtındaki satırların anahtarlarıdır (__ ile başlayanlar hariç).
Her satırda bir seçim kutusu, eşlenen kolondan okunan ilk dolu değeri (Örnek:) ve üstte N / M alan eşleşti sayacı bulunur. Zorunlu olmayan bir alanın eşlemesi temizlenebilir; boş bırakılan alan sunucuya hiç gönderilmez.
Otomatik eşleşme
Adım açıldığında her alan için, henüz kullanılmamış Excel kolonları arasından en yüksek puanlı olan seçilir (bire bir):
| Puan | Koşul |
|---|---|
| 100 | Başlıktaki teknik ek kolonun name'ine eşit: Ürün Kodu <ProCode> → ProCode |
| 90 | Teknik eki atılmış başlık, kolonun header'ına eşit (büyük/küçük harf duyarsız) |
| 80 | Teknik eki atılmış başlık, kolonun name'ine eşit |
| 70 | Normalize edilmiş başlık, normalize edilmiş header'a eşit |
| 60 | Normalize edilmiş başlık, normalize edilmiş name'e eşit |
Normalize etmek; Türkçe İ/ı harflerini ve aksanları sadeleştirip harf ve rakam
dışındaki her şeyi atmak demektir (Masraf Grubu = masraf_grubu). Teknik ek,
başlığın sonunda yalnızca harf, rakam ve _ içerdiğinde tanınır (<ProCode>);
headerPolicy: 'tech-suffix' ile indirilen şablonlarda kullanıcı görünen
başlığı değiştirse bile kolon doğru alana oturur. Kullanıcının varsayılan
eşleştirme profili varsa otomatik eşleşmenin yerine o uygulanır.
Bir alana, başka bir alanın kullandığı Excel kolonu seçilirse iki alanın kolonları yer değiştirir; seçim engellenmez.
Birleştirme (Kod + Ad)
Satırın yanındaki küçük + düğmesi alanı birleştirme kipine alır. Kolonlar sırayla eklenir, ← ile sola taşınır, × ile çıkarılır; iki ve daha fazla kolon olduğunda ayraç seçilir ve sonucun canlı bir örneği gösterilir. Birleştirme her veri tipindeki alanda kullanılabilir.
| Ayraç | Değer |
|---|---|
- (varsayılan) | " - " |
| Boşluk | " " |
/ | " / " |
_ | "_" |
, | ", " |
| Bitişik | "" |
| Özel | En çok 10 karakter, serbest |
- Boş parçalar atlanır; parçaların hepsi boşsa alan o satırda boş kalır.
- Parçalar Excel'de görünen metinden okunur; baştaki sıfırlar ve hücre biçimi korunur. Birleşimin sonucu her zaman metindir.
- Birleşik bir alan, başka bir alanın tek başına kullandığı kolonu da içerebilir (ör. Kod hem kendi alanında hem Kod - Ad içinde).
- ↶ Birleştirmeyi geri al alanı birleştirmeye başlamadan önceki haline (tek kolon ya da boş) döndürür. Bu bilinmiyorsa — ör. birleşim bir profilden geldiyse ya da kullanıcı adımdan çıkıp geri döndüyse — listedeki ilk kolon kalır.
Tek kolonlu eşlemede string ve guid alanlar da görünen metinden okunur;
diğer tiplerde ham hücre değeri gider (tarihler ISO 8601 metnine çevrilir).
Doğrulama ve uygulama
İki durum Eşlemeyi Uygula ve Devam düğmesini kilitler: eşlenmemiş zorunlu bir alan ve aynı Excel kolonunun tek başına birden fazla alana bağlanması. Kural birleşimlere uygulanmaz.
Uygulandığında eşlenmiş satırlar validate-rows ile sunucuda doğrulanır. Hata
varsa sihirbaz önizlemeye döner; kullanıcı eşleme adımına geri geldiğinde
hatalı alanlar kırmızı işaretlenir (N satırda hata · mesaj), üstte toplam
hata sayısı ve Ön izlemede düzelt düğmesi çıkar. Eşleme uygulandıktan sonra
değiştirilirse sihirbaz uyarır: yeniden uygulamak, önizlemedeki hücre
düzenlemelerini Excel verisinden baştan üretir.
Alan bazlı işaretleme
CellError.columnüzerinden yapılır: sunucu bu alana sözleşmedeki kolonunnamedeğerini aynen yazmalıdır.column'u boş hatalar yalnızca toplam hata sayısına girer.
Eşleştirme profilleri
Kullanıcı kurduğu eşlemeyi bir ad vererek saklayabilir ve sonraki aktarımlarda tek tıkla uygulayabilir. Profiller kullanıcıya ve process key'e özeldir; kolon sırasını değil Excel başlık metinlerini saklar, bu sayede aynı başlıkları taşıyan başka bir dosyada da çalışır.
Provider'da dataExchange.mappingProfilesUrl (hazır REST deposu) ya da
dataExchange.mappingProfileStorage (özel depo) verildiğinde eşleştirme
adımının üstünde Eşleştirme profilim çubuğu çıkar. İkisi de grid ya da
sihirbaz düzeyinde config.dataExchange ile verilebilir; profil ayarları
provider'dakilerle alan alan birleştirilir.
Kullanıcı tarafı
- Profil seç — seçilen profil eşlemeyi doldurur. Profildeki bir başlık bu dosyada yoksa durum satırında bu dosyada bulunamayan kolon uyarısı çıkar; profil uygulandıktan sonra eşleme değiştirilirse kaydedilmemiş değişiklik var yazar.
- Kaydet — ad (en çok 200 karakter) ve Varsayılan yap seçeneğiyle kaydeder. Aynı adla kayıtlı profil varsa düğme Güncelle olur; üzerine yazmayı sunucu yapar (bkz. kaydetme gövdesi). Hiç profil yokken Varsayılan yap işaretli gelir; seçili bir profil varsa form onun adı ve varsayılan durumuyla açılır.
- ★ Varsayılan — seçili profili varsayılan yapar ya da varsayılanlıktan çıkarır. Varsayılan profil, sihirbazda Önizle'ye basıldığında otomatik eşleşmenin yerine kendiliğinden uygulanır. Sihirbaz profil listesini en çok 3 saniye bekler; liste gecikirse otomatik eşleşmeyle devam eder.
- Sil — onay sorusundan sonra profili siler.
Profil listesi yüklenemezse çubukta Profiller yüklenemedi; eşlemeyi elle yapabilirsiniz. yazar; içe aktarma engellenmez. Kaydetme, silme ve varsayılan değiştirme hataları da çubuğun durum satırında gösterilir.
Profil bir dosyaya nasıl uygulanır: her başlık önce görünen metniyle birebir,
bulunamazsa teknik eki atılıp normalize edilerek aranır. Profilde null
kaydedilmiş alan bilerek eşlenmemiş kalır. Profilde hiç yer almayan (sözleşmeye
sonradan eklenmiş) ya da kolonlarının hiçbiri dosyada bulunamayan alanlar
otomatik eşleşmeye bırakılır.
REST sözleşmesi — mappingProfilesUrl
mappingProfilesUrl verildiğinde livalib, createColumnMappingProfileApiStorage
ile şu uçları çağırır ({base} sondaki / atılmış taban; {processKey} ve
{id} URL kodlanır):
| İşlem | İstek | Beklenen yanıt |
|---|---|---|
| Listele | GET {base}/{processKey} | 200 + profil dizisi. 204 ya da dizi olmayan gövde boş liste sayılır. |
| Kaydet | POST {base}/{processKey} | 2xx + { "id": "…" } |
| Sil | DELETE {base}/{processKey}/{id} | 2xx (gövde okunmaz) |
| Varsayılan yap | PUT {base}/{processKey}/{id}/default | 2xx |
| Varsayılanı kaldır | DELETE {base}/{processKey}/default | 2xx |
İstekler sihirbazın diğer çağrılarıyla aynı başlıkları taşır (Authorization: Bearer …, Accept-Language) ve provider'daki fetch'i kullanır; yalnızca
POST gövdelidir (Content-Type: application/json). Kullanıcı kimliği
gönderilmez — sunucu kullanıcıyı oturumdan/token'dan çözmeli ve kimse başkasının
profiline erişememelidir. DELETE …/{id} ile DELETE …/default aynı biçimde
olduğundan sunucuda {id} rotasını kısıtlayın (ör. {id:guid}); aksi halde
default bir kimlik gibi silme rotasına düşer.
Liste satırı. Alan adları camelCase ya da PascalCase olabilir (id/Id,
name/Name, mapping/Mapping, isDefault/IsDefault, uDate/UDate):
[
{
"id": "8d0c6a7e-1b2f-4c55-9a1e-3f6b2d7c9e10",
"name": "Tedarikçi Excel'i",
"mapping": "{\"version\":1,\"fields\":{…}}",
"isDefault": true,
"uDate": "2026-10-31T09:12:00"
}
]
id ya da name'i boş olan, mapping'i metin olmayan, JSON olarak
ayrıştırılamayan veya fields nesnesi taşımayan satırlar sessizce atlanır.
uDate isteğe bağlıdır.
Kaydetme gövdesi:
{
"name": "Tedarikçi Excel'i",
"mapping": "{\"version\":1,\"fields\":{…}}",
"isDefault": true
}
isDefault: true varsayılan yapar, false varsayılanlıktan çıkarır, alan
hiç yoksa varsayılan durumu değişmez. Kaydetme isteği kimlik taşımaz; çubuk
aynı adı Güncelle olarak sunduğu için sunucu kaydı kullanıcı + process key +
ad üzerinden ekleyip güncellemelidir. Sihirbaz listedeki ilk isDefault
profili uyguladığından süreç başına tek varsayılan tutulmalıdır.
mapping metni sunucu için opaktır — olduğu gibi saklanıp geri
döndürülmelidir. İçeriği { version: 1, fields } biçimindedir; okurken
yalnızca fields kullanılır:
{
"version": 1,
"fields": {
"ExpCode": { "sources": ["Masraf Kodu"], "separator": " - " },
"ExpName": { "sources": ["Kod", "Ad"], "separator": " - " },
"Note": null
}
}
fields tipi ColumnMappingProfileFields'tır: anahtar sözleşmedeki kolonun
name'i, sources sırasıyla Excel başlık metinleri (tekrarlayan başlıklar
Başlık (2) biçiminde), null ise bilerek eşlenmemiş alan.
2xx dışı her yanıt "{METOT} {url} → {durum}" mesajlı bir hata olarak çubukta
görünür.
Özel depo — ColumnMappingProfileStorage
Profilleri başka bir yerde tutmak ya da farklı bir API'ye bağlamak için
mappingProfileStorage'a bu arayüzü uygulayan bir nesne verin:
interface ColumnMappingProfileStorage {
list(processKey: string): Promise<ColumnMappingProfile[]>;
save(processKey: string, request: ColumnMappingProfileSaveRequest): Promise<{ id: string }>;
remove(processKey: string, id: string): Promise<void>;
setDefault(processKey: string, id: string | null): Promise<void>; // null → varsayılanı kaldır
}
interface ColumnMappingProfile {
id: string;
name: string;
isDefault: boolean;
fields: ColumnMappingProfileFields;
updatedAt?: string | null;
}
interface ColumnMappingProfileSaveRequest {
name: string;
fields: ColumnMappingProfileFields;
isDefault?: boolean; // true → varsayılan yap, false → çıkar, undefined → değiştirme
}
Kullanıcıyı depo belirler; arayüz kullanıcı kimliği almaz. Her save,
remove ve setDefault çağrısından sonra liste list ile yeniden okunur.
import type { ColumnMappingProfile, ColumnMappingProfileStorage } from "@dataliva/livalib";
const anahtar = (processKey: string) => `import-profiles:${processKey}`;
const oku = (processKey: string): ColumnMappingProfile[] =>
JSON.parse(localStorage.getItem(anahtar(processKey)) ?? "[]");
const yaz = (processKey: string, list: ColumnMappingProfile[]) =>
localStorage.setItem(anahtar(processKey), JSON.stringify(list));
// Modül düzeyinde: referans sabit kalır.
export const yerelProfilDeposu: ColumnMappingProfileStorage = {
list: async processKey => oku(processKey),
save: async (processKey, request) => {
const list = oku(processKey);
const mevcut = list.find(p => p.name === request.name);
const id = mevcut?.id ?? crypto.randomUUID();
let next = [
...list.filter(p => p.id !== id),
{ id, name: request.name, fields: request.fields, isDefault: request.isDefault ?? mevcut?.isDefault ?? false },
];
if (request.isDefault) next = next.map(p => ({ ...p, isDefault: p.id === id }));
yaz(processKey, next);
return { id };
},
remove: async (processKey, id) => yaz(processKey, oku(processKey).filter(p => p.id !== id)),
setDefault: async (processKey, id) =>
yaz(processKey, oku(processKey).map(p => ({ ...p, isDefault: p.id === id }))),
};
<LivaGridConfigProvider dataExchange={{ baseUrl, mappingProfileStorage: yerelProfilDeposu }}>
Depo nesnesini modül düzeyinde ya da
useMemoile sabit tutun. Her render'da yeni bir nesne verilirse sihirbaz açıkken profil listesi her render'da yeniden istenir.
Hazır REST deposunu kendi yapılandırmanızla kurmak için
createColumnMappingProfileApiStorage(config, baseUrl) kullanılabilir; config
bir LivaGridConfig ya da onu döndüren bir fonksiyondur (token, lang ve
fetch buradan okunur). mappingProfilesUrl verildiğinde livalib bunu
provider yapılandırmasıyla kendisi kurar.
Serbest kullanım — useDataExchange
Sihirbaz dışında kendi arayüzünüzü kurmak için düşük seviyeli kanca. Uç nokta
çözümlemesi, başlıklar ve routeParams'ın her isteğin gövdesine route olarak
eklenmesi sizin yerinize yapılır.
const dx = useDataExchange({ processKey: "expense-definition", routeParams: { budgetYear } });
const blob = await dx.downloadTemplate(true); // verili şablon
saveBlobAs(blob, "masraf-tanimi.xlsx");
const onizleme = await dx.validate(file);
if (onizleme.errors.length === 0) {
const rapor = await dx.importFile(file);
}
| Metot | Döner | Açıklama |
|---|---|---|
fetchContract() | DataExchangeContract | Sözleşmeyi okur. |
downloadTemplate(withData?) | Blob | withData: true verili şablon indirir (POST). |
exportData(payload?) | Blob | Dışa aktarma; payload nesnesinin alanları gövdeye route ile birlikte yazılır. |
validate(file) | DataExchangePreview | Dosyayı doğrular (multipart). |
validateRows(rows) | DataExchangePreview | Düzenlenmiş satırları doğrular. |
validateSource(kind, options) | DataExchangePreview | Adaptör kaynağını doğrular. |
importFile(file) | DataExchangeReport | Dosyayı içe aktarır. |
importRows(rows) | DataExchangeReport | Satırları içe aktarır. |
importSource(kind, options) | DataExchangeReport | Adaptör kaynağından içe aktarır. |
fetchAdapters(capability) | DataExchangeAdapterDescriptor[] | 'read' veya 'write' kataloğu. |
endpoints | DataExchangeEndpoints | Çözümlenmiş uç noktalar. |
useContract(opts) yalnızca sözleşmeyi getirir ve { contract, loading, error }
döner — opts.contract verilmişse istek atılmaz. saveBlobAs(blob, filename)
dönen blob'u tarayıcıya indirtir.
Sözleşme tipleri
DataExchangeContract sunucunun bildirdiği şemadır:
| Alan | Tip | Açıklama |
|---|---|---|
processKey | string | Süreç anahtarı |
displayNameKey | string | null | Çeviri anahtarı |
headerPolicy | { technicalSuffix, suffixFormat } | Şablon başlık biçimi |
upsertKey | string[] | Kaydın kimliğini oluşturan alanlar |
columns | ColumnContract[] | Kolon şeması |
autoProvisions | AutoProvisionContract[] | Eksik kayıt otomatik oluşturma kuralları |
ColumnContract: name, header, dataType, required, order,
groupHeader?, lookup? (registry / codeField / idField / labelField),
monthSeries? (prefix / count / countFrom / labelKey), enum?
(enumName / values / labelResource) ve autoProvision?.
DataExchangePreview: contract, rows, errors, totalRows,
plannedInsertCount?, plannedUpdateCount?.
DataExchangeReport: totalRows, insertedCount, updatedCount,
errorCount, autoProvisionedCount, recordsBefore?, recordsAfter?,
errors, messages.
CellError: rowNumber, column?, bucket, message — bucket hatanın
sınıfıdır (biçim, lookup, zorunluluk vb.) ve önizlemede gruplama için kullanılır.
column kolonun name değerini taşımalıdır: önizlemede hatalı hücre ve kolon
eşleştirme adımında hatalı alan bununla bulunur.
Adaptörler
Bir adaptör, verinin nereden okunacağını tanımlar. Katalog sunucudan gelir;
AdapterPicker ve AdapterFieldsForm bileşenleri sihirbazın ilk adımını
oluşturur ve dışa da açılmıştır.
| Alan | Tip | Açıklama |
|---|---|---|
key | string | Adaptör kimliği |
displayNameKey / descriptionKey | string | Çeviri anahtarları |
icon | string | null | DevExtreme ikon adı |
capabilities | string[] | ["read"] veya ["read", "write"] |
transport | 'multipart' | 'json' | 'source' | Kullanılacak HTTP yüzeyi |
selectable | boolean | Katalogda kullanıcıya gösterilir mi |
fields | AdapterField[] | Kaynak adımında doldurulacak alanlar |
AdapterField: name, labelKey, type ('file' \| 'text' \| 'lookup'),
required, lookupKey? ve lookupContext?. lookupContext değerleri
"${processKey}" biçiminde şablon değişkeni içerebilir; sihirbaz bunları kendi
durumundan (processKey + routeParams) doldurur.
transport: "json" yalnızca sihirbazın kendi iç satır akışı içindir; kullanıcıya
sunulan bir adaptör için multipart ya da source kullanılır.