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, önizleme ve içe aktarma adımlarını kendisi yürütür — sayfada elle Excel ayrıştırma kodu kalmaz.
import {
LivaGridConfigProvider,
LivaImportWizard,
useDataExchange,
useContract,
type DataExchangeContract,
} 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` }}
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. |
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. |
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.
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 isteklere query string olarak eklenir. |
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. |
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.
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}
/>
| 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 | — |
translate | (key: string) => string | — |
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. - Önizleme —
validateçağrılır; dönenDataExchangePreviewsatırları veerrorslistesini tablo üzerinde gösterir. Hücreler burada düzenlenebilir; düzenleme yapıldığında satırlarvalidate-rowsile yeniden doğrulanır. - Onay — hata kalmadıysa açılır. Planlanan ekleme/güncelleme sayıları
(
plannedInsertCount,plannedUpdateCount) burada gösterilir. - Rapor —
DataExchangeReportözeti.closeOnCompleteverilmedikçe sihirbaz bu adımda açık kalır.
Önizlemede satır düzenlendiyse içe aktarma, kaynak adaptörü ne olursa olsun
import-rowsüzerinden gönderilir — kullanıcının düzelttiği değerler böyle korunur.
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 query string birleştirme 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. |
exportData(payload?) | Blob | Dışa aktarma. |
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.
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.