LivaDocsv1.0.112

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>
AlanTipAçıklama
dataExchange.baseUrlstringUç nokta kökü. Varsayılan /api/data-exchange.
dataExchange.endpointsResolver(processKey) => DataExchangeEndpointsRota ş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.
tokenstring | (() => string | undefined)Fonksiyon verin; token yenilendiğinde provider'ı yeniden render etmeye gerek kalmaz.
langstringAccept-Language başlığı (ör. "TR").
fetchtypeof fetchTest veya interceptor için fetch değişimi.

baseUrl verildiğinde uç noktalar şu kalıptan türetilir:

Uç noktaRota
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",
  }}
/>
AlanTipAçıklama
enabledbooleanAraç çubuğundaki içe/dışa aktarma butonunu açar.
processKeystringSözleşme anahtarı. Verildiğinde sihirbaz devreye girer.
baseUrlstringYalnızca bu grid için kök adres değişimi.
endpointsPartial<DataExchangeEndpoints>Tek tek uç nokta ezme.
headerPolicy'tech-suffix' | 'header-only'Başlık politikası ezme.
contractDataExchangeContractSözleşme elde varsa definition isteği atlanır.
autoProvisionRecord<string, boolean>Eksik kayıtların otomatik oluşturulmasını alan bazında aç/kapat.
routeParamsRecord<string, string | number | boolean | null | undefined>Tüm isteklere query string olarak eklenir.
configPartial<LivaGridConfig>Provider yapılandırmasını bu grid için ezer.
wizardTitlestringSihirbaz başlığı.
closeOnCompletebooleanVarsayı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}
/>
PropTipVarsayılan
processKeystring— (zorunlu)
visibleboolean— (zorunlu)
onHiding() => void— (zorunlu)
baseUrlstring
endpointsPartial<DataExchangeEndpoints>
contractDataExchangeContract— (verilirse definition isteği atlanır)
routeParamsRouteParams
configPartial<LivaGridConfig>
onCompleted(report: DataExchangeReport) => void
titlestring
translate(key: string) => string

Adımlar

  1. Kaynak — adaptör kataloğu capability=read ile çekilir. Katalogda tek adaptör varsa kendiliğinden seçilir. Adaptörün transport değeri akışı belirler: multipart dosya yükler, source ise adaptörün kendi alanlarını (fields) doldurtup sunucudan okur.
  2. Önizlemevalidate çağrılır; dönen DataExchangePreview satırları ve errors listesini tablo üzerinde gösterir. Hücreler burada düzenlenebilir; düzenleme yapıldığında satırlar validate-rows ile yeniden doğrulanır.
  3. Onay — hata kalmadıysa açılır. Planlanan ekleme/güncelleme sayıları (plannedInsertCount, plannedUpdateCount) burada gösterilir.
  4. RaporDataExchangeReport özeti. closeOnComplete verilmedikç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);
}
MetotDönerAçıklama
fetchContract()DataExchangeContractSözleşmeyi okur.
downloadTemplate(withData?)BlobwithData: true verili şablon indirir.
exportData(payload?)BlobDışa aktarma.
validate(file)DataExchangePreviewDosyayı doğrular (multipart).
validateRows(rows)DataExchangePreviewDüzenlenmiş satırları doğrular.
validateSource(kind, options)DataExchangePreviewAdaptör kaynağını doğrular.
importFile(file)DataExchangeReportDosyayı içe aktarır.
importRows(rows)DataExchangeReportSatırları içe aktarır.
importSource(kind, options)DataExchangeReportAdaptör kaynağından içe aktarır.
fetchAdapters(capability)DataExchangeAdapterDescriptor[]'read' veya 'write' kataloğu.
endpointsDataExchangeEndpointsÇö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:

AlanTipAçıklama
processKeystringSüreç anahtarı
displayNameKeystring | nullÇeviri anahtarı
headerPolicy{ technicalSuffix, suffixFormat }Şablon başlık biçimi
upsertKeystring[]Kaydın kimliğini oluşturan alanlar
columnsColumnContract[]Kolon şeması
autoProvisionsAutoProvisionContract[]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, messagebucket 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.

AlanTipAçıklama
keystringAdaptör kimliği
displayNameKey / descriptionKeystringÇeviri anahtarları
iconstring | nullDevExtreme ikon adı
capabilitiesstring[]["read"] veya ["read", "write"]
transport'multipart' | 'json' | 'source'Kullanılacak HTTP yüzeyi
selectablebooleanKatalogda kullanıcıya gösterilir mi
fieldsAdapterField[]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.