Cascading sistem AI tarafından elde geçirildi.
This commit is contained in:
parent
81b2202df0
commit
021ddd03d1
7 changed files with 101 additions and 304 deletions
7
.github/instructions/lowcode.instructions.md
vendored
7
.github/instructions/lowcode.instructions.md
vendored
|
|
@ -1352,8 +1352,8 @@ cascade eksik yetenek değildir ve analizde `Ready to Start`'ı engellemez. Tam
|
|||
| `DataSourceType` | `1` StaticData · `2` Query · `3` WebService |
|
||||
| `ValueExpr` / `DisplayExpr` | Varsayılan `Key` / `Name` |
|
||||
| `LookupQuery` | Kaynağın kendisi (tipe göre biçim değişir, aşağıda) |
|
||||
| `CascadeParentFields` | **Çocuk alanda** doldurulur; değerleri sorguya taşınacak ebeveyn alan(lar), virgülle. Sırayla `@param0`, `@param1`… olur (`Query`/`WebService`); gelmeyen parametre `NULL` bağlanır |
|
||||
| `CascadeRelationField` | **Çocuk alanda** doldurulur; `StaticData`'da ebeveynin değeriyle karşılaştırılan alan (öğedeki `group`) |
|
||||
| `CascadeParentFields` | **Çocuk alanda** doldurulur; değerleri sorguya taşınacak ebeveyn alan(lar), virgülle. Sırayla `@param0`, `@param1`… olur (`Query`/`WebService`); boş ya da gelmeyen ebeveyn `NULL` bağlanır. Değer her zaman **metin** parametre olarak bağlanır (`ListFormSelectAppService.ToLookupParameter`), sayı anahtarlı ebeveyn de çalışır; dönüşümü kolon tipine göre veritabanı yapar. `WebService` gövdesine değer JSON kaçışlı yazılır |
|
||||
| `CascadeRelationField` | **Çocuk alanda**, yalnızca `StaticData`'da anlamlıdır: öğede ilk ebeveynin değeriyle karşılaştırılan alan; boşsa `group`. Ebeveyn boşken liste süzülmez |
|
||||
| `CascadeFilterOperator` | `StaticData` cascade filtresinin operatörü; varsayılan `=` |
|
||||
| `CascadeEmptyFields` | **Ebeveyn alanda** doldurulur; bu alan değişince boşaltılacak çocuk alanlar, virgülle. Ara halka (İl) hem çocuk hem ebeveyn olduğu için iki tarafı birden taşır |
|
||||
|
||||
|
|
@ -1409,7 +1409,8 @@ ya da `EditorOptions`'ta `grouped: true` vardır ve öğeler `group` alanı taş
|
|||
`[Key]` + `[Name]` takma adlarını döndürür ve `ValueExpr: "Key"`, `DisplayExpr: "Name"` yazılır.
|
||||
Bağımlı liste `grouped` ile değil cascade ile kurulur.
|
||||
|
||||
> Lookup verisi önbelleklenir; aynı sorgu aynı filtrelerle bir kez yüklenir.
|
||||
> Lookup verisi önbelleklenir; aynı sorgu aynı filtrelerle bir kez yüklenir. Grid, Tree, Card ve
|
||||
> Form aynı veri kaynağını kullanır (`views/form/useLookupDataSource.ts`); cascade kuralı tek yerdedir.
|
||||
|
||||
### 4.3.5 Varsayılan değerler — `*FieldsDefaultValueJson`
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ public class LookupRequestDto
|
|||
{
|
||||
public string ListFormCode { get; set; }
|
||||
public string ListFormFieldName { get; set; }
|
||||
public string[] Filters { get; set; }
|
||||
/// <summary>Cascade ebeveyn degerleri, <c>CascadeParentFields</c> sirasiyla; sayi ya da metin olabilir.</summary>
|
||||
public object[] Filters { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -418,22 +418,17 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
|
|||
var lookup = JsonSerializer.Deserialize<LookupDto>(field.LookupJson);
|
||||
if (!string.IsNullOrWhiteSpace(lookup?.LookupQuery))
|
||||
{
|
||||
var parameters = new Dictionary<string, object>();
|
||||
if (input.Filters != null)
|
||||
{
|
||||
for (int i = 0; i < input.Filters.Length; i++)
|
||||
{
|
||||
parameters.Add("@param" + i, input.Filters[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Cascade ebeveyn degerleri @param0… olarak baglanir; gelmeyen ebeveyn NULL olur ki
|
||||
// sorgu "(Kolon = @param0 OR @param0 IS NULL)" kalibiyla tum listeyi donsun.
|
||||
var cascadeParameterCount = lookup.CascadeParentFields?
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Length ?? 0;
|
||||
var parameterCount = Math.Max(input.Filters?.Length ?? 0, cascadeParameterCount);
|
||||
|
||||
for (int i = input.Filters?.Length ?? 0; i < cascadeParameterCount; i++)
|
||||
var parameters = new Dictionary<string, object>();
|
||||
for (var i = 0; i < parameterCount; i++)
|
||||
{
|
||||
parameters.Add("@param" + i, null!);
|
||||
parameters.Add("@param" + i, ToLookupParameter(input.Filters, i)!);
|
||||
}
|
||||
|
||||
var lookupQuery = defaultValueHelper.GetDefaultValue(lookup.LookupQuery);
|
||||
|
|
@ -444,6 +439,26 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
|
|||
return new List<LookupDataDto>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ebeveyn degeri istemcide sayi, metin ya da bool olabilir; parametre her zaman metin olarak
|
||||
/// baglanir ki sorgudaki kolon tipine gore veritabani donustursun (int kolona "5" de gider).
|
||||
/// </summary>
|
||||
private static string? ToLookupParameter(object[]? filters, int index)
|
||||
{
|
||||
var value = filters is not null && index < filters.Length ? filters[index] : null;
|
||||
|
||||
return value switch
|
||||
{
|
||||
null => null,
|
||||
JsonElement { ValueKind: JsonValueKind.Null or JsonValueKind.Undefined } => null,
|
||||
JsonElement { ValueKind: JsonValueKind.String } element => NullIfEmpty(element.GetString()),
|
||||
JsonElement element => element.GetRawText(),
|
||||
_ => NullIfEmpty(Convert.ToString(value, CultureInfo.InvariantCulture))
|
||||
};
|
||||
|
||||
static string? NullIfEmpty(string? text) => string.IsNullOrEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
public async Task<string> GetNextSequenceValueAsync(string SequenceName)
|
||||
{
|
||||
var sequenceManager = LazyServiceProvider.LazyGetRequiredService<SequenceManager>();
|
||||
|
|
@ -451,93 +466,6 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
|
|||
return await sequenceManager.GetNextSequenceAsync(SequenceName);
|
||||
}
|
||||
|
||||
private static string WrapLookupQueryWithInFilter(
|
||||
string lookupQuery,
|
||||
string listFormSelectCommand,
|
||||
string listFormFieldName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(lookupQuery))
|
||||
throw new ArgumentException("LookupQuery boş olamaz.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(listFormSelectCommand))
|
||||
throw new ArgumentException("SelectCommand boş olamaz.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(listFormFieldName))
|
||||
throw new ArgumentException("ListFormFieldName boş olamaz.");
|
||||
|
||||
return $@"
|
||||
SELECT *
|
||||
FROM (
|
||||
{lookupQuery}
|
||||
) t
|
||||
WHERE ""Key"" IN (
|
||||
SELECT ""{listFormFieldName}""
|
||||
FROM ""{listFormSelectCommand}""
|
||||
GROUP BY ""{listFormFieldName}""
|
||||
)";
|
||||
}
|
||||
|
||||
private static string AddCascadeWhereCondition(
|
||||
string sql,
|
||||
string cascadeParentFields,
|
||||
int paramStartIndex = 0)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sql))
|
||||
throw new ArgumentException("SQL boş olamaz.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cascadeParentFields))
|
||||
return sql;
|
||||
|
||||
var fields = cascadeParentFields
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(f => f.Trim())
|
||||
.ToArray();
|
||||
|
||||
if (!fields.Any())
|
||||
return sql;
|
||||
|
||||
var conditions = new List<string>();
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
|
||||
// Zaten " ile başlıyorsa dokunma
|
||||
if (!field.StartsWith("\""))
|
||||
field = $"\"{field}\"";
|
||||
|
||||
conditions.Add($"{field} = @param{paramStartIndex + i}");
|
||||
}
|
||||
|
||||
string whereClause = string.Join(" AND ", conditions);
|
||||
var upperSql = sql.ToUpperInvariant();
|
||||
|
||||
if (upperSql.Contains(" WHERE "))
|
||||
{
|
||||
return InsertBeforeClause(sql, "AND " + whereClause);
|
||||
}
|
||||
else
|
||||
{
|
||||
return InsertBeforeClause(sql, "WHERE " + whereClause);
|
||||
}
|
||||
}
|
||||
|
||||
private static string InsertBeforeClause(string sql, string insertText)
|
||||
{
|
||||
var upperSql = sql.ToUpperInvariant();
|
||||
string[] clauses = { " GROUP BY ", " ORDER BY ", " HAVING " };
|
||||
|
||||
foreach (var clause in clauses)
|
||||
{
|
||||
int index = upperSql.IndexOf(clause);
|
||||
if (index > -1)
|
||||
{
|
||||
return sql.Insert(index, " " + insertText + " ");
|
||||
}
|
||||
}
|
||||
|
||||
return sql + " " + insertText;
|
||||
}
|
||||
|
||||
//Workflow kriterlerini alma
|
||||
private async Task<List<ListFormWorkflowCriteriaDto>> GetWorkflowCriteriaAsync(string listFormCode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ type BuildFormItemsParams = {
|
|||
mode: RowMode
|
||||
columns?: GridColumnData[]
|
||||
/** Lookup alanları için DevExtreme dataSource üretici. */
|
||||
getLookupDataSource: (options: any, colData: ColumnFormatDto, formData: any) => any
|
||||
getLookupDataSource: (colData: ColumnFormatDto, formData: any) => any
|
||||
formData: any
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ const toFormItem = (
|
|||
|
||||
const lookupEditorOptions = colFormat.lookupDto?.dataSourceType
|
||||
? {
|
||||
dataSource: getLookupDataSource(colFormat.editorOptions, colFormat, formData),
|
||||
dataSource: getLookupDataSource(colFormat, formData),
|
||||
valueExpr: colFormat.lookupDto?.valueExpr?.toLowerCase(),
|
||||
displayExpr: colFormat.lookupDto?.displayExpr?.toLowerCase(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ const useGridData = (props: {
|
|||
...item.editorOptions,
|
||||
dataSource: keepCustomDataSource
|
||||
? currentDataSource
|
||||
: getLookupDataSource(colData?.editorOptions, colData, formData || null),
|
||||
: getLookupDataSource(colData, formData || null),
|
||||
valueExpr:
|
||||
item.editorOptions?.valueExpr ?? colData?.lookupDto?.valueExpr?.toLowerCase(),
|
||||
displayExpr:
|
||||
|
|
|
|||
|
|
@ -14,17 +14,48 @@ export { clearLookupCache } from '../shared/lookupCache'
|
|||
const isLookupAllowed = (listFormCode?: string, isSubForm?: boolean) =>
|
||||
isSubForm || !listFormCode || window.location.pathname.includes(listFormCode)
|
||||
|
||||
const createLookupStaticDataSource = (
|
||||
const splitFields = (value?: string | null) =>
|
||||
(value ?? '')
|
||||
.split(',')
|
||||
.map((field) => field.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
const isEmptyValue = (value: unknown) => value === undefined || value === null || value === ''
|
||||
|
||||
/**
|
||||
* Cascade filtresi. Query/WebService için ebeveyn değerleri sırayla `@param0…` olur; boş ebeveyn
|
||||
* `null` gider ve sorgu `(Kolon = @param0 OR @param0 IS NULL)` kalıbıyla tüm listeyi döner.
|
||||
* StaticData için öğelerdeki `CascadeRelationField` alanı (varsayılan `group`) ilk ebeveynin
|
||||
* değeriyle karşılaştırılır; ebeveyn boşsa süzülmez.
|
||||
*/
|
||||
export const buildCascadeFilters = (lookupDto: any, rowData: any): any[] | null => {
|
||||
const parentFields = splitFields(lookupDto?.cascadeParentFields)
|
||||
if (!parentFields.length) return null
|
||||
|
||||
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
|
||||
const parentValue = rowData?.[parentFields[0]]
|
||||
if (isEmptyValue(parentValue)) return null
|
||||
|
||||
return [
|
||||
lookupDto.cascadeRelationField || 'group',
|
||||
lookupDto.cascadeFilterOperator || '=',
|
||||
parentValue,
|
||||
]
|
||||
}
|
||||
|
||||
return parentFields.map((field) => (isEmptyValue(rowData?.[field]) ? null : rowData[field]))
|
||||
}
|
||||
|
||||
export const createLookupStaticDataSource = (
|
||||
load: () => any,
|
||||
filter: any = null,
|
||||
key: any = 'static',
|
||||
sort: any = 'name',
|
||||
filter: any[] | null,
|
||||
cacheKey: string,
|
||||
sort = 'name',
|
||||
) => ({
|
||||
store: new CustomStore({
|
||||
key,
|
||||
loadMode: 'raw',
|
||||
load: () =>
|
||||
cachedLookupLoad(`static:${key}`, async () => {
|
||||
cachedLookupLoad(`static:${cacheKey}`, async () => {
|
||||
const result = await Promise.resolve(load())
|
||||
if (result === undefined || result === null) return []
|
||||
return Array.isArray(result) ? result : [result]
|
||||
|
|
@ -34,10 +65,10 @@ const createLookupStaticDataSource = (
|
|||
filter,
|
||||
})
|
||||
|
||||
const createLookupQueryDataSource = (
|
||||
export const createLookupQueryDataSource = (
|
||||
listFormCode?: string,
|
||||
listFormFieldName?: string,
|
||||
filters?: any[],
|
||||
filters?: any[] | null,
|
||||
isSubForm?: boolean,
|
||||
) =>
|
||||
new CustomStore({
|
||||
|
|
@ -72,10 +103,13 @@ const createLookupQueryDataSource = (
|
|||
},
|
||||
})
|
||||
|
||||
const createLookupApiDataSource = (
|
||||
/** Gövde JSON şablonudur; değer tırnak içine yerleştiği için JSON kaçışlı yazılır. */
|
||||
const toJsonText = (value: unknown) => (value === null ? 'null' : JSON.stringify(String(value)).slice(1, -1))
|
||||
|
||||
export const createLookupApiDataSource = (
|
||||
listFormCode?: string,
|
||||
lookupQuery?: string,
|
||||
filters?: any[],
|
||||
filters?: any[] | null,
|
||||
keyName?: string,
|
||||
isSubForm?: boolean,
|
||||
) =>
|
||||
|
|
@ -99,7 +133,7 @@ const createLookupApiDataSource = (
|
|||
// Gövdedeki @param0, @param1… yer tutucularını cascade filtreleriyle doldur.
|
||||
let resolvedBody = bodyTemplate ?? ''
|
||||
filters?.forEach((filterValue, index) => {
|
||||
resolvedBody = resolvedBody.replace(new RegExp(`@param${index}`, 'g'), String(filterValue))
|
||||
resolvedBody = resolvedBody.replace(new RegExp(`@param${index}\\b`, 'g'), toJsonText(filterValue))
|
||||
})
|
||||
|
||||
try {
|
||||
|
|
@ -129,6 +163,10 @@ const createLookupApiDataSource = (
|
|||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Lookup kolonunun veri kaynağı. Grid/Tree/Card (`useListFormColumns`) ve Form aynı kuralı
|
||||
* kullanır; `rowData` cascade ebeveynlerinin okunduğu kayıttır.
|
||||
*/
|
||||
export const useLookupDataSource = ({
|
||||
listFormCode,
|
||||
isSubForm,
|
||||
|
|
@ -139,24 +177,9 @@ export const useLookupDataSource = ({
|
|||
const { translate, cultureName } = useLocalization()
|
||||
|
||||
const getLookupDataSource = useCallback(
|
||||
(options: any, colData: any, data: any) => {
|
||||
(colData: any, rowData: any) => {
|
||||
const { lookupDto } = colData
|
||||
const filters: any[] = []
|
||||
|
||||
// Cascading alanlar: parent değeri yoksa null gönderilir, istek yine de yapılır.
|
||||
if (lookupDto.cascadeParentFields) {
|
||||
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
|
||||
filters.push([
|
||||
lookupDto?.cascadeRelationField,
|
||||
lookupDto?.cascadeFilterOperator,
|
||||
options?.data?.[lookupDto?.cascadeParentField] ?? null,
|
||||
])
|
||||
} else {
|
||||
for (const cascadeParentField of lookupDto.cascadeParentFields.split(',')) {
|
||||
filters.push(data?.[cascadeParentField.trim()] ?? null)
|
||||
}
|
||||
}
|
||||
}
|
||||
const filters = buildCascadeFilters(lookupDto, rowData)
|
||||
|
||||
switch (lookupDto.dataSourceType) {
|
||||
case UiLookupDataSourceTypeEnum.StaticData:
|
||||
|
|
@ -166,8 +189,8 @@ export const useLookupDataSource = ({
|
|||
...item,
|
||||
name: typeof item.name === 'string' ? translate(`::${item.name}`) : item.name,
|
||||
})),
|
||||
filters.length ? filters : null,
|
||||
`static:${cultureName}:${listFormCode}:${colData.fieldName}`,
|
||||
filters,
|
||||
`${cultureName}:${listFormCode}:${colData.fieldName}`,
|
||||
)
|
||||
case UiLookupDataSourceTypeEnum.Query:
|
||||
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters, isSubForm)
|
||||
|
|
|
|||
|
|
@ -17,11 +17,8 @@ import {
|
|||
UiLookupDataSourceTypeEnum,
|
||||
} from '@/proxy/form/models'
|
||||
import { addCss, getEditingFormFields } from './Utils'
|
||||
import {
|
||||
cachedLookupLoad,
|
||||
clearLookupCache,
|
||||
clearLookupCacheByPrefix,
|
||||
} from '../shared/lookupCache'
|
||||
import { clearLookupCache, clearLookupCacheByPrefix } from '../shared/lookupCache'
|
||||
import { useLookupDataSource } from '../form/useLookupDataSource'
|
||||
import {
|
||||
NO_IMAGE,
|
||||
normalizeImageSize,
|
||||
|
|
@ -169,7 +166,7 @@ const useListFormColumns = ({
|
|||
onShowNote?: (rowData: Record<string, any>) => void
|
||||
}) => {
|
||||
const dialog: any = useDialogContext()
|
||||
const { translate, cultureName } = useLocalization()
|
||||
const { translate } = useLocalization()
|
||||
const { checkPermission } = usePermission()
|
||||
const isPwaMode = usePWA()
|
||||
|
||||
|
|
@ -178,55 +175,12 @@ const useListFormColumns = ({
|
|||
clearLookupCache()
|
||||
}, [listFormCode])
|
||||
|
||||
const { getLookupDataSource } = useLookupDataSource({ listFormCode, isSubForm })
|
||||
|
||||
// DataGrid lookup'ı satırı `options.data` ile verir; görünen metin yüklemesi satırsız çağırır.
|
||||
const lookupDataSource = useCallback(
|
||||
(options: any, colData: any, listFormCode: string) => {
|
||||
const { lookupDto } = colData
|
||||
const filters = []
|
||||
if (lookupDto.cascadeParentFields) {
|
||||
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
|
||||
filters.push([
|
||||
lookupDto?.cascadeRelationField,
|
||||
lookupDto?.cascadeFilterOperator,
|
||||
options?.data[lookupDto?.cascadeParentField],
|
||||
])
|
||||
//TODO: Statik data test edilecek
|
||||
} else {
|
||||
const data = options?.data ?? options
|
||||
for (const cascadeParentField of lookupDto.cascadeParentFields.split(',')) {
|
||||
filters.push(data[cascadeParentField])
|
||||
}
|
||||
}
|
||||
}
|
||||
//UiLookupDataSourceTypeEnum :
|
||||
// Data = 1 (Statik Data),
|
||||
// Query = 2 (API'den geliyor fakat API query çalıştırıyor)
|
||||
// WebService = 3 (API servisten geliyor)
|
||||
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
|
||||
return createLookupStaticDataSource(
|
||||
() =>
|
||||
JSON.parse(lookupDto?.lookupQuery).map((item: any) => ({
|
||||
...item,
|
||||
name: typeof item.name === 'string' ? translate(`::${item.name}`) : item.name,
|
||||
})),
|
||||
filters.length ? filters : null,
|
||||
`static:${cultureName}:${listFormCode}:${colData.fieldName}`, // cache key
|
||||
)
|
||||
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
|
||||
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters)
|
||||
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.WebService) {
|
||||
return createLookupApiDataSource(
|
||||
listFormCode,
|
||||
lookupDto?.lookupQuery,
|
||||
filters,
|
||||
colData.lookupDto?.valueExpr?.toLowerCase(),
|
||||
)
|
||||
} else {
|
||||
return {
|
||||
store: [],
|
||||
}
|
||||
}
|
||||
},
|
||||
[listFormCode, translate, cultureName],
|
||||
(options: any, colData: any) => getLookupDataSource(colData, options?.data ?? options),
|
||||
[getLookupDataSource],
|
||||
)
|
||||
|
||||
const loadLookupDisplayValues = useCallback(
|
||||
|
|
@ -241,7 +195,7 @@ const useListFormColumns = ({
|
|||
)
|
||||
.map(async (column) => {
|
||||
const lookup = column.colData!.lookupDto
|
||||
const source = lookupDataSource({}, column.colData, listFormCode)
|
||||
const source = lookupDataSource({}, column.colData)
|
||||
const store =
|
||||
source instanceof CustomStore
|
||||
? source
|
||||
|
|
@ -270,7 +224,7 @@ const useListFormColumns = ({
|
|||
|
||||
return Object.fromEntries(entries) as Record<string, Map<string, string>>
|
||||
},
|
||||
[listFormCode, lookupDataSource],
|
||||
[lookupDataSource],
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -311,7 +265,7 @@ const useListFormColumns = ({
|
|||
const prefix = getCachePrefix(colData)
|
||||
if (!prefix) return
|
||||
|
||||
const source = lookupDataSource({}, colData, listFormCode)
|
||||
const source = lookupDataSource({}, colData)
|
||||
const store =
|
||||
source instanceof CustomStore
|
||||
? source
|
||||
|
|
@ -347,115 +301,6 @@ const useListFormColumns = ({
|
|||
[gridDto, listFormCode, lookupDataSource],
|
||||
)
|
||||
|
||||
const createLookupStaticDataSource = (
|
||||
load: () => any,
|
||||
filter: any = null,
|
||||
key: any = 'static',
|
||||
sort: any = 'name',
|
||||
) => ({
|
||||
store: new CustomStore({
|
||||
key,
|
||||
loadMode: 'raw',
|
||||
load: async () => {
|
||||
// load fonksiyonu sync sonuç döndürüyor olabilir, o yüzden Promise.resolve ile sar
|
||||
return cachedLookupLoad(`static:${key}`, async () => {
|
||||
const result = await Promise.resolve(load())
|
||||
if (result === undefined || result === null) return []
|
||||
return Array.isArray(result) ? result : [result]
|
||||
})
|
||||
},
|
||||
}),
|
||||
sort,
|
||||
filter,
|
||||
})
|
||||
|
||||
const createLookupQueryDataSource = (
|
||||
listFormCode?: string,
|
||||
listFormFieldName?: string,
|
||||
filters?: any[],
|
||||
) => {
|
||||
return new CustomStore({
|
||||
loadMode: 'raw',
|
||||
load: async () => {
|
||||
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
|
||||
return []
|
||||
}
|
||||
|
||||
try {
|
||||
const cacheKey = `query:${listFormCode}:${listFormFieldName}:${JSON.stringify(filters ?? null)}`
|
||||
return cachedLookupLoad(cacheKey, async () => {
|
||||
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
|
||||
listFormCode,
|
||||
listFormFieldName,
|
||||
filters,
|
||||
})
|
||||
|
||||
return (response.data ?? []).map((a: any) => ({
|
||||
key: a.Key,
|
||||
name: a.Name,
|
||||
group: a.Group,
|
||||
|
||||
...a,
|
||||
}))
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Lookup query data could not be loaded:', error)
|
||||
return []
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const createLookupApiDataSource = (
|
||||
listFormCode?: string,
|
||||
lookupQuery?: string,
|
||||
filters?: any[],
|
||||
keyName?: string,
|
||||
) => {
|
||||
return new CustomStore({
|
||||
key: keyName,
|
||||
loadMode: 'raw',
|
||||
load: async () => {
|
||||
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
|
||||
return []
|
||||
}
|
||||
if (!lookupQuery) {
|
||||
return []
|
||||
}
|
||||
|
||||
const [method, url, body, keySelector, nameSelector, groupSelector] = lookupQuery.split(';')
|
||||
|
||||
// body içindeki @paramN'leri filtrelerle değiştir
|
||||
let resolvedBody = body
|
||||
if (filters?.length) {
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
resolvedBody = resolvedBody.replace(new RegExp(`@param${i}`, 'g'), filters[i])
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const cacheKey = `api:${lookupQuery}:${JSON.stringify(filters ?? null)}`
|
||||
return cachedLookupLoad(cacheKey, async () => {
|
||||
const response = await dynamicFetch(url, method, null, resolvedBody)
|
||||
let { data } = response
|
||||
if (!data) return []
|
||||
if (!Array.isArray(data)) data = [data]
|
||||
return data.map((a: any) => ({
|
||||
key: eval(keySelector),
|
||||
name: eval(nameSelector),
|
||||
group: eval(groupSelector),
|
||||
|
||||
...a,
|
||||
}))
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Lookup API data could not be loaded:', error)
|
||||
return []
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const getCommandColumn = useCallback((): GridColumnData | undefined => {
|
||||
if (!gridDto) {
|
||||
return
|
||||
|
|
@ -817,9 +662,8 @@ const useListFormColumns = ({
|
|||
column.lookup = {
|
||||
valueExpr: colData.lookupDto?.valueExpr?.toLowerCase(),
|
||||
displayExpr: colData.lookupDto?.displayExpr?.toLowerCase(),
|
||||
dataSource: (o) => lookupDataSource(o, colData, listFormCode),
|
||||
dataSource: (o) => lookupDataSource(o, colData),
|
||||
}
|
||||
//column.lookup.dataSource = lookupDataSource(null, colData)
|
||||
|
||||
//cascadeEmptyFields verisi dolu ise bu kolon/field bir parent field dir
|
||||
if (colData.lookupDto.cascadeEmptyFields) {
|
||||
|
|
@ -891,7 +735,7 @@ const useListFormColumns = ({
|
|||
|
||||
return columns
|
||||
},
|
||||
[gridDto, lookupDataSource, translate, checkPermission, dialog, isPwaMode, listFormCode],
|
||||
[gridDto, lookupDataSource, translate],
|
||||
)
|
||||
|
||||
const getBandedColumns = useCallback(() => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue