erp-platform/ui/src/views/form/useLookupDataSource.ts

183 lines
5.3 KiB
TypeScript
Raw Normal View History

2025-09-21 20:05:13 +00:00
import { dynamicFetch } from '@/services/form.service'
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
import CustomStore from 'devextreme/data/custom_store'
import { useCallback } from 'react'
2025-10-22 14:58:27 +00:00
const __lookupCache = new Map<string, Promise<any[]>>()
const cachedLoader = (key: string, loader: () => Promise<any[]>) => {
if (__lookupCache.has(key)) return __lookupCache.get(key)!
const p = Promise.resolve()
.then(() => loader())
.then((res) => res ?? [])
.catch((err) => {
__lookupCache.delete(key)
throw err
})
__lookupCache.set(key, p)
return p
}
2025-09-21 20:05:13 +00:00
const createLookupStaticDataSource = (
load: () => any,
filter: any = null,
2025-10-22 14:58:27 +00:00
key: any = 'static',
2025-09-21 20:05:13 +00:00
sort: any = 'name',
) => ({
store: new CustomStore({
key,
loadMode: 'raw',
2025-10-22 14:58:27 +00:00
load: async () => {
const cacheKey = `static:${key}`
return cachedLoader(cacheKey, async () => {
const res = await Promise.resolve(load())
return Array.isArray(res) ? res : [res]
})
},
2025-09-21 20:05:13 +00:00
}),
sort,
filter,
})
const createLookupQueryDataSource = (
listFormCode?: string,
listFormFieldName?: string,
filters?: any[],
isSubForm?: boolean,
) => {
return new CustomStore({
loadMode: 'raw',
load: async () => {
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
return
}
2025-10-22 14:58:27 +00:00
const cacheKey = `query:${listFormCode}:${listFormFieldName}:${JSON.stringify(filters ?? null)}`
return cachedLoader(cacheKey, async () => {
2025-09-21 20:05:13 +00:00
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
listFormCode,
listFormFieldName,
filters,
})
2025-10-22 14:58:27 +00:00
const data = response?.data ?? []
return (Array.isArray(data) ? data : [data]).map((a: any) => ({
2025-09-21 20:05:13 +00:00
key: a.Key,
name: a.Name,
group: a.Group,
}))
2025-10-22 14:58:27 +00:00
}).catch(() => null as any)
2025-09-21 20:05:13 +00:00
},
})
}
const createLookupApiDataSource = (
listFormCode?: string,
lookupQuery?: string,
filters?: any[],
keyName?: string,
isSubForm?: boolean,
) => {
return new CustomStore({
key: keyName,
loadMode: 'raw',
load: async () => {
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
return
}
if (!lookupQuery) {
return
}
2025-10-22 14:58:27 +00:00
const parts = lookupQuery.split(';')
const [
method = 'GET',
url = '',
bodyTemplate = '',
keySelector = 'a=>a.id',
nameSelector = 'a=>a.name',
groupSelector = 'a=>a.group',
] = parts
2025-09-21 20:05:13 +00:00
2025-10-22 14:58:27 +00:00
let resolvedBody = bodyTemplate ?? ''
2025-09-21 20:05:13 +00:00
if (filters?.length) {
for (let i = 0; i < filters.length; i++) {
2025-10-22 14:58:27 +00:00
resolvedBody = resolvedBody.replace(new RegExp(`@param${i}`, 'g'), String(filters[i]))
2025-09-21 20:05:13 +00:00
}
}
2025-10-22 14:58:27 +00:00
const cacheKey = `api:${lookupQuery}:${JSON.stringify(filters ?? null)}`
return cachedLoader(cacheKey, async () => {
const response = await dynamicFetch(url, method, null, resolvedBody)
2025-09-21 20:05:13 +00:00
let { data } = response
2025-10-22 14:58:27 +00:00
if (!data) return []
if (!Array.isArray(data)) data = [data]
2025-09-21 20:05:13 +00:00
return data.map((a: any) => ({
key: eval(keySelector),
name: eval(nameSelector),
group: eval(groupSelector),
}))
2025-10-22 14:58:27 +00:00
}).catch(() => [] as any)
2025-09-21 20:05:13 +00:00
},
})
}
export const useLookupDataSource = ({
listFormCode,
isSubForm,
}: {
listFormCode: string
isSubForm?: boolean
}) => {
const getLookupDataSource = useCallback(
2025-10-22 14:58:27 +00:00
(options: any, colData: any, data: any) => {
2025-09-21 20:05:13 +00:00
const { lookupDto } = colData
2025-10-22 14:58:27 +00:00
const filters: any[] = []
// Cascading field'ler için - data yoksa veya parent field değeri yoksa null parametreler ile API çağrısı yap
2025-09-21 20:05:13 +00:00
if (lookupDto.cascadeParentFields) {
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
filters.push([
lookupDto?.cascadeRelationField,
lookupDto?.cascadeFilterOperator,
options?.data?.[lookupDto?.cascadeParentField] ?? null,
2025-09-21 20:05:13 +00:00
])
} else {
for (const cascadeParentField of lookupDto.cascadeParentFields.split(',')) {
2025-10-02 07:47:14 +00:00
filters.push(data?.[cascadeParentField] ?? null)
2025-09-21 20:05:13 +00:00
}
}
}
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
2025-10-22 14:58:27 +00:00
const staticKey = `static:${listFormCode}:${colData.fieldName}`
2025-09-21 20:05:13 +00:00
return createLookupStaticDataSource(
() => JSON.parse(lookupDto?.lookupQuery),
filters.length ? filters : null,
2025-10-22 14:58:27 +00:00
staticKey,
2025-09-21 20:05:13 +00:00
)
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters, isSubForm)
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.WebService) {
return createLookupApiDataSource(
listFormCode,
lookupDto?.lookupQuery,
filters,
colData.lookupDto?.valueExpr?.toLowerCase(),
isSubForm,
)
} else {
2025-10-22 14:58:27 +00:00
return { store: [] }
2025-09-21 20:05:13 +00:00
}
},
[listFormCode, isSubForm],
)
return { getLookupDataSource }
}
2025-10-22 14:58:27 +00:00
/** Opsiyonel: dışarıdan cache temizlemek istersen export et */
export const clearLookupCache = (key?: string) => {
if (!key) __lookupCache.clear()
else __lookupCache.delete(key)
}