editorScript ve Seeder
This commit is contained in:
parent
65af5fa231
commit
ea37ef0682
15 changed files with 324 additions and 296 deletions
|
|
@ -46,5 +46,6 @@ public class EditingFormItemDto
|
||||||
public bool IsRequired { get; set; }
|
public bool IsRequired { get; set; }
|
||||||
public GridBoxOptionsDto GridBoxOptions { get; set; }
|
public GridBoxOptionsDto GridBoxOptions { get; set; }
|
||||||
public TagBoxOptionsDto TagBoxOptions { get; set; }
|
public TagBoxOptionsDto TagBoxOptions { get; set; }
|
||||||
public string Script { get; set; }
|
[JsonPropertyName("editorScript")]
|
||||||
|
public string EditorScript { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35399,9 +35399,9 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
new EditingFormItemDto { Order = 1, DataField = "AppliedDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox},
|
new EditingFormItemDto { Order = 1, DataField = "AppliedDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox},
|
||||||
new EditingFormItemDto { Order = 2, DataField = "EmployeeId", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
|
new EditingFormItemDto { Order = 2, DataField = "EmployeeId", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
|
||||||
new EditingFormItemDto { Order = 3, DataField = "LeaveType", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
|
new EditingFormItemDto { Order = 3, DataField = "LeaveType", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox },
|
||||||
new EditingFormItemDto { Order = 4, DataField = "StartDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox},
|
new EditingFormItemDto { Order = 4, DataField = "StartDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox, EditorScript = EditorOptionValues.DateDiffStartDateEndDate},
|
||||||
new EditingFormItemDto { Order = 5, DataField = "EndDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox},
|
new EditingFormItemDto { Order = 5, DataField = "EndDate", ColSpan = 2, IsRequired=true, EditorType2 = EditorTypes.dxDateBox, EditorScript = EditorOptionValues.DateDiffStartDateEndDate},
|
||||||
new EditingFormItemDto { Order = 6, DataField = "TotalDays", ColSpan = 2, EditorType2 = EditorTypes.dxNumberBox},
|
new EditingFormItemDto { Order = 6, DataField = "TotalDays", ColSpan = 2, EditorType2 = EditorTypes.dxNumberBox, EditorOptions = EditorOptionValues.Disabled},
|
||||||
new EditingFormItemDto { Order = 7, DataField = "IsHalfDay", ColSpan = 2, EditorType2 = EditorTypes.dxCheckBox},
|
new EditingFormItemDto { Order = 7, DataField = "IsHalfDay", ColSpan = 2, EditorType2 = EditorTypes.dxCheckBox},
|
||||||
new EditingFormItemDto { Order = 8, DataField = "Reason", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextArea},
|
new EditingFormItemDto { Order = 8, DataField = "Reason", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextArea},
|
||||||
new EditingFormItemDto { Order = 9, DataField = "Status", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox},
|
new EditingFormItemDto { Order = 9, DataField = "Status", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox},
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,11 @@ public static class PlatformConsts
|
||||||
|
|
||||||
public static class EditorOptionValues
|
public static class EditorOptionValues
|
||||||
{
|
{
|
||||||
|
public static string Disabled = "{ \"disabled\" : true }";
|
||||||
public static string ShowClearButton = "{ \"showClearButton\" : true }";
|
public static string ShowClearButton = "{ \"showClearButton\" : true }";
|
||||||
public static string HtmlEditorOptions = "{\"toolbar\": {\"multiline\": true, \"items\": [{\"name\": \"undo\"},{\"name\": \"redo\"},{\"name\": \"separator\"},{\"name\": \"size\",\"acceptedValues\": [\"8pt\",\"10pt\",\"12pt\",\"14pt\",\"18pt\",\"24pt\",\"36pt\"],\"options\": {\"inputAttr\": {\"aria-label\": \"Font size\"}}},{\"name\": \"font\",\"acceptedValues\": [\"Arial\",\"Courier New\",\"Georgia\",\"Impact\",\"Lucida Console\",\"Tahoma\",\"Times New Roman\",\"Verdana\"],\"options\": {\"inputAttr\": {\"aria-label\": \"Font family\"}}},{\"name\": \"separator\"},{\"name\": \"bold\"},{\"name\": \"italic\"},{\"name\": \"strike\"},{\"name\": \"underline\"},{\"name\": \"separator\"},{\"name\": \"alignLeft\"},{\"name\": \"alignCenter\"},{\"name\": \"alignRight\"},{\"name\": \"alignJustify\"},{\"name\": \"separator\"},{\"name\": \"orderedList\"},{\"name\": \"bulletList\"},{\"name\": \"separator\"},{\"name\": \"header\",\"acceptedValues\": [false,1,2,3,4,5],\"options\": {\"inputAttr\": {\"aria-label\": \"Font family\"}}},{\"name\": \"separator\"},{\"name\": \"color\"},{\"name\": \"background\"},{\"name\": \"separator\"},{\"name\": \"link\"},{\"name\": \"image\"},{\"name\": \"separator\"},{\"name\": \"clear\"},{\"name\": \"codeBlock\"},{\"name\": \"blockquote\"},{\"name\": \"separator\"},{\"name\": \"insertTable\"},{\"name\": \"deleteTable\"},{\"name\": \"insertRowAbove\"},{\"name\": \"insertRowBelow\"},{\"name\": \"deleteRow\"},{\"name\": \"insertColumnLeft\"},{\"name\": \"insertColumnRight\"},{\"name\": \"deleteColumn\"}]}}";
|
public static string HtmlEditorOptions = "{\"toolbar\": {\"multiline\": true, \"items\": [{\"name\": \"undo\"},{\"name\": \"redo\"},{\"name\": \"separator\"},{\"name\": \"size\",\"acceptedValues\": [\"8pt\",\"10pt\",\"12pt\",\"14pt\",\"18pt\",\"24pt\",\"36pt\"],\"options\": {\"inputAttr\": {\"aria-label\": \"Font size\"}}},{\"name\": \"font\",\"acceptedValues\": [\"Arial\",\"Courier New\",\"Georgia\",\"Impact\",\"Lucida Console\",\"Tahoma\",\"Times New Roman\",\"Verdana\"],\"options\": {\"inputAttr\": {\"aria-label\": \"Font family\"}}},{\"name\": \"separator\"},{\"name\": \"bold\"},{\"name\": \"italic\"},{\"name\": \"strike\"},{\"name\": \"underline\"},{\"name\": \"separator\"},{\"name\": \"alignLeft\"},{\"name\": \"alignCenter\"},{\"name\": \"alignRight\"},{\"name\": \"alignJustify\"},{\"name\": \"separator\"},{\"name\": \"orderedList\"},{\"name\": \"bulletList\"},{\"name\": \"separator\"},{\"name\": \"header\",\"acceptedValues\": [false,1,2,3,4,5],\"options\": {\"inputAttr\": {\"aria-label\": \"Font family\"}}},{\"name\": \"separator\"},{\"name\": \"color\"},{\"name\": \"background\"},{\"name\": \"separator\"},{\"name\": \"link\"},{\"name\": \"image\"},{\"name\": \"separator\"},{\"name\": \"clear\"},{\"name\": \"codeBlock\"},{\"name\": \"blockquote\"},{\"name\": \"separator\"},{\"name\": \"insertTable\"},{\"name\": \"deleteTable\"},{\"name\": \"insertRowAbove\"},{\"name\": \"insertRowBelow\"},{\"name\": \"deleteRow\"},{\"name\": \"insertColumnLeft\"},{\"name\": \"insertColumnRight\"},{\"name\": \"deleteColumn\"}]}}";
|
||||||
public static string PhoneEditorOptions = "{\"format\": \"phoneGlobal\", \"mask\":\"(000) 000-0000\", \"maskInvalidMessage\":\"Lütfen geçerli bir telefon numarası girin\", \"useMaskedValue\":false, \"maskRules\": { \"X\": \"[1-9]\" }, \"placeholder\": \"(555) 123-4567\" }";
|
public static string PhoneEditorOptions = "{\"format\": \"phoneGlobal\", \"mask\":\"(000) 000-0000\", \"maskInvalidMessage\":\"Lütfen geçerli bir telefon numarası girin\", \"useMaskedValue\":false, \"maskRules\": { \"X\": \"[1-9]\" }, \"placeholder\": \"(555) 123-4567\" }";
|
||||||
|
public static string DateDiffStartDateEndDate = "(() => {const d=v=>!v?null:(v instanceof Date?v:new Date(v));const nf={...formData,[editor.dataField]:e?.value};const s=d(nf.StartDate),t=d(nf.EndDate);setFormData({...formData,TotalDays: s&&t?Math.max(0,Math.floor((Date.UTC(t.getFullYear(),t.getMonth(),t.getDate())-Date.UTC(s.getFullYear(),s.getMonth(),s.getDate()))/(24*60*60*1000))+1):null});})();";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Prefix
|
public static class Prefix
|
||||||
|
|
|
||||||
|
|
@ -2719,14 +2719,14 @@
|
||||||
"district": "Ankara",
|
"district": "Ankara",
|
||||||
"street": "Kızılay Cd. No:12",
|
"street": "Kızılay Cd. No:12",
|
||||||
"postalCode": "06050",
|
"postalCode": "06050",
|
||||||
"phone": "+90 212 555 0100",
|
"phone": "2125550100",
|
||||||
"personalPhone": "+90 532 555 0101",
|
"personalPhone": "5325550101",
|
||||||
"email": "ali.ozturk@company.com",
|
"email": "ali.ozturk@company.com",
|
||||||
"address1": "",
|
"address1": "",
|
||||||
"address2": "",
|
"address2": "",
|
||||||
"emergencyContactname": "Ayşe Öztürk",
|
"emergencyContactname": "Ayşe Öztürk",
|
||||||
"emergencyContactrelationship": "Eşi",
|
"emergencyContactrelationship": "Eşi",
|
||||||
"emergencyContactphone": "+90 532 555 0100",
|
"emergencyContactphone": "5325550100",
|
||||||
"hireDate": "15-01-2020",
|
"hireDate": "15-01-2020",
|
||||||
"terminationDate": "15-01-2020",
|
"terminationDate": "15-01-2020",
|
||||||
"employmentTypeName": "FullTime",
|
"employmentTypeName": "FullTime",
|
||||||
|
|
@ -2759,14 +2759,14 @@
|
||||||
"district": "Ankara",
|
"district": "Ankara",
|
||||||
"street": "İnönü Bulvarı No:456",
|
"street": "İnönü Bulvarı No:456",
|
||||||
"postalCode": "06000",
|
"postalCode": "06000",
|
||||||
"phone": "+90 212 555 0102",
|
"phone": "2125550102",
|
||||||
"personalPhone": "+90 532 555 0103",
|
"personalPhone": "5325550103",
|
||||||
"email": "ayse.kaya@company.com",
|
"email": "ayse.kaya@company.com",
|
||||||
"address1": "",
|
"address1": "",
|
||||||
"address2": "",
|
"address2": "",
|
||||||
"emergencyContactname": "Fatma Kaya",
|
"emergencyContactname": "Fatma Kaya",
|
||||||
"emergencyContactrelationship": "Anne",
|
"emergencyContactrelationship": "Anne",
|
||||||
"emergencyContactphone": "+90 532 555 0104",
|
"emergencyContactphone": "5325550104",
|
||||||
"hireDate": "01-06-2021",
|
"hireDate": "01-06-2021",
|
||||||
"terminationDate": "",
|
"terminationDate": "",
|
||||||
"employmentTypeName": "FullTime",
|
"employmentTypeName": "FullTime",
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,7 @@ export interface EditingFormItemDto {
|
||||||
isRequired?: boolean
|
isRequired?: boolean
|
||||||
gridBoxOptions?: GridBoxOptionsDto
|
gridBoxOptions?: GridBoxOptionsDto
|
||||||
tagBoxOptions?: TagBoxOptionsDto
|
tagBoxOptions?: TagBoxOptionsDto
|
||||||
script?: string
|
editorScript?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GridEditingPopupDto {
|
export interface GridEditingPopupDto {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
UiCommandButtonPositionTypeEnum,
|
UiCommandButtonPositionTypeEnum,
|
||||||
UiLookupDataSourceTypeEnum,
|
UiLookupDataSourceTypeEnum,
|
||||||
} from '../proxy/form/models'
|
} from '../proxy/form/models'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
const cellTemplateMultiValue = (
|
const cellTemplateMultiValue = (
|
||||||
cellElement: HTMLElement,
|
cellElement: HTMLElement,
|
||||||
|
|
@ -82,6 +83,22 @@ function calculateFilterExpressionMultiValue(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookup cache (module scope)
|
||||||
|
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) // hata olursa tekrar denenebilsin
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
__lookupCache.set(key, p)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
const useListFormColumns = ({
|
const useListFormColumns = ({
|
||||||
gridDto,
|
gridDto,
|
||||||
listFormCode,
|
listFormCode,
|
||||||
|
|
@ -98,6 +115,11 @@ const useListFormColumns = ({
|
||||||
const { checkPermission } = usePermission()
|
const { checkPermission } = usePermission()
|
||||||
const isPwaMode = usePWA()
|
const isPwaMode = usePWA()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// listFormCode değişince lookup cache temizlensin (farklı form farklı lookuplar)
|
||||||
|
__lookupCache.clear()
|
||||||
|
}, [listFormCode])
|
||||||
|
|
||||||
const lookupDataSource = (options: any, colData: any, listFormCode: string) => {
|
const lookupDataSource = (options: any, colData: any, listFormCode: string) => {
|
||||||
const { lookupDto } = colData
|
const { lookupDto } = colData
|
||||||
const filters = []
|
const filters = []
|
||||||
|
|
@ -124,6 +146,7 @@ const useListFormColumns = ({
|
||||||
return createLookupStaticDataSource(
|
return createLookupStaticDataSource(
|
||||||
() => JSON.parse(lookupDto?.lookupQuery),
|
() => JSON.parse(lookupDto?.lookupQuery),
|
||||||
filters.length ? filters : null,
|
filters.length ? filters : null,
|
||||||
|
`static:${listFormCode}:${colData.fieldName}`, // cache key
|
||||||
)
|
)
|
||||||
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
|
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
|
||||||
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters)
|
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters)
|
||||||
|
|
@ -144,13 +167,16 @@ const useListFormColumns = ({
|
||||||
const createLookupStaticDataSource = (
|
const createLookupStaticDataSource = (
|
||||||
load: () => any,
|
load: () => any,
|
||||||
filter: any = null,
|
filter: any = null,
|
||||||
key: any = 'key',
|
key: any = 'static',
|
||||||
sort: any = 'name',
|
sort: any = 'name',
|
||||||
) => ({
|
) => ({
|
||||||
store: new CustomStore({
|
store: new CustomStore({
|
||||||
key,
|
key,
|
||||||
loadMode: 'raw',
|
loadMode: 'raw',
|
||||||
load,
|
load: async (loadOptions) => {
|
||||||
|
// load fonksiyonu sync sonuç döndürüyor olabilir, o yüzden Promise.resolve ile sar
|
||||||
|
return cachedLoader(`static:${key}`, () => Promise.resolve(load()))
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
sort,
|
sort,
|
||||||
filter,
|
filter,
|
||||||
|
|
@ -169,27 +195,21 @@ const useListFormColumns = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const cacheKey = `query:${listFormCode}:${listFormFieldName}:${JSON.stringify(filters ?? null)}`
|
||||||
|
return cachedLoader(cacheKey, async () => {
|
||||||
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
|
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
|
||||||
listFormCode,
|
listFormCode,
|
||||||
listFormFieldName,
|
listFormFieldName,
|
||||||
filters,
|
filters,
|
||||||
})
|
})
|
||||||
|
|
||||||
return response.data.map((a: any) => ({
|
return (response.data ?? []).map((a: any) => ({
|
||||||
key: a.Key,
|
key: a.Key,
|
||||||
name: a.Name,
|
name: a.Name,
|
||||||
group: a.Group,
|
group: a.Group,
|
||||||
}))
|
}))
|
||||||
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
// toast.push(
|
|
||||||
// <Notification type="danger" duration={2000}>
|
|
||||||
// Select error
|
|
||||||
// {error.toString()}
|
|
||||||
// </Notification>,
|
|
||||||
// {
|
|
||||||
// placement: 'top-end',
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -206,7 +226,6 @@ const useListFormColumns = ({
|
||||||
key: keyName,
|
key: keyName,
|
||||||
loadMode: 'raw',
|
loadMode: 'raw',
|
||||||
load: async (loadOptions) => {
|
load: async (loadOptions) => {
|
||||||
//Sayfa degismisse istek yapma
|
|
||||||
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
|
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -215,48 +234,29 @@ const useListFormColumns = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
const [method, url, body, keySelector, nameSelector, groupSelector] = lookupQuery.split(';')
|
const [method, url, body, keySelector, nameSelector, groupSelector] = lookupQuery.split(';')
|
||||||
//POST;https://tcmb.gov.tr/api/doviz;{"dovizType":@param0};a=>a.DovizId;a=>a.DovizName;a=>a.Ulke
|
|
||||||
|
|
||||||
//TODO: Body dinamik params test edilecek
|
// body içindeki @paramN'leri filtrelerle değiştir
|
||||||
|
let resolvedBody = body
|
||||||
if (filters?.length) {
|
if (filters?.length) {
|
||||||
for (let i = 0; i < filters.length; i++) {
|
for (let i = 0; i < filters.length; i++) {
|
||||||
body.replace(`@param${i}`, filters[i])
|
resolvedBody = resolvedBody.replace(new RegExp(`@param${i}`, 'g'), filters[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await dynamicFetch(url, method, null, body)
|
const cacheKey = `api:${lookupQuery}:${JSON.stringify(filters ?? null)}`
|
||||||
|
return cachedLoader(cacheKey, async () => {
|
||||||
|
const response = await dynamicFetch(url, method, null, resolvedBody)
|
||||||
let { data } = response
|
let { data } = response
|
||||||
if (!data) {
|
if (!data) return []
|
||||||
// toast.push(
|
if (!Array.isArray(data)) data = [data]
|
||||||
// <Notification type="danger" duration={2000}>
|
|
||||||
// {'Lookup Datası boş geldi.'}
|
|
||||||
// </Notification>,
|
|
||||||
// {
|
|
||||||
// placement: 'top-end',
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(data)) {
|
|
||||||
data = [data]
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.map((a: any) => ({
|
return data.map((a: any) => ({
|
||||||
key: eval(keySelector),
|
key: eval(keySelector),
|
||||||
name: eval(nameSelector),
|
name: eval(nameSelector),
|
||||||
group: eval(groupSelector),
|
group: eval(groupSelector),
|
||||||
}))
|
}))
|
||||||
|
})
|
||||||
} catch {
|
} catch {
|
||||||
// toast.push(
|
|
||||||
// <Notification type="danger" duration={2000}>
|
|
||||||
// {'Network error'}
|
|
||||||
// </Notification>,
|
|
||||||
// {
|
|
||||||
// placement: 'top-end',
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -740,9 +740,9 @@ function JsonRowOpDialogEditForm({
|
||||||
<Field
|
<Field
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
name={`items.${index}.script`}
|
name={`items.${index}.editorScript`}
|
||||||
component={Input}
|
component={Input}
|
||||||
placeholder="Script"
|
placeholder="Editor Script"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-1/12 ml-2 align-middle text-center">
|
<div className="w-1/12 ml-2 align-middle text-center">
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ import { GridColumnData } from '../list/GridColumnData'
|
||||||
import { useToolbar } from '../list/useToolbar'
|
import { useToolbar } from '../list/useToolbar'
|
||||||
import { PermissionResults, RowMode } from './types'
|
import { PermissionResults, RowMode } from './types'
|
||||||
import { GridDto } from '@/proxy/form/models'
|
import { GridDto } from '@/proxy/form/models'
|
||||||
import React from 'react'
|
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import { usePermission } from '@/utils/hooks/usePermission'
|
import { usePermission } from '@/utils/hooks/usePermission'
|
||||||
import { GridExtraFilterState } from '../list/Utils'
|
import { GridExtraFilterState } from '../list/Utils'
|
||||||
|
|
@ -214,7 +213,8 @@ const FormButtons = (props: {
|
||||||
if (onActionNew) {
|
if (onActionNew) {
|
||||||
onActionNew()
|
onActionNew()
|
||||||
} else {
|
} else {
|
||||||
navigate(ROUTES_ENUM.protected.admin.formNew.replace(':listFormCode', listFormCode))
|
navigate(ROUTES_ENUM.protected.admin.formNew
|
||||||
|
.replace(':listFormCode', listFormCode))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
{...(permissions.c ? {} : { disabled: true })}
|
{...(permissions.c ? {} : { disabled: true })}
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,12 @@ const FormDevExpress = (props: {
|
||||||
.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
|
.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
|
||||||
.find((i: SimpleItemWithColData) => i.dataField === e.dataField)
|
.find((i: SimpleItemWithColData) => i.dataField === e.dataField)
|
||||||
|
|
||||||
if (changeItem?.script) {
|
if (changeItem?.editorScript) {
|
||||||
try {
|
try {
|
||||||
//setFormData({...formData, Path: e.value});
|
//setFormData({...formData, Path: e.value});
|
||||||
//UiEvalService.ApiGenerateBackgroundWorkers();
|
//UiEvalService.ApiGenerateBackgroundWorkers();
|
||||||
//setFormData({ ...formData, Path: (v => v === '1' ? '1-deneme' : v === '0' ? '0-deneme' : '')(e.value) })
|
//setFormData({ ...formData, Path: (v => v === '1' ? '1-deneme' : v === '0' ? '0-deneme' : '')(e.value) })
|
||||||
eval(changeItem.script)
|
eval(changeItem.editorScript)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Script execution failed for', changeItem.name, err)
|
console.error('Script execution failed for', changeItem.name, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export type SimpleItemWithColData = Overwrite<
|
||||||
canUpdate: boolean
|
canUpdate: boolean
|
||||||
canExport: boolean
|
canExport: boolean
|
||||||
editorType2: EditorType2
|
editorType2: EditorType2
|
||||||
script?: string
|
editorScript?: string
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
export type RowMode = 'view' | 'edit' | 'new'
|
export type RowMode = 'view' | 'edit' | 'new'
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ const useGridData = (props: {
|
||||||
colData,
|
colData,
|
||||||
tagBoxOptions: i.tagBoxOptions,
|
tagBoxOptions: i.tagBoxOptions,
|
||||||
gridBoxOptions: i.gridBoxOptions,
|
gridBoxOptions: i.gridBoxOptions,
|
||||||
script: i.script,
|
editorScript: i.editorScript,
|
||||||
}
|
}
|
||||||
if (i.dataField.indexOf(':') >= 0) {
|
if (i.dataField.indexOf(':') >= 0) {
|
||||||
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,44 @@
|
||||||
|
// src/.../useLookupDataSource.ts
|
||||||
import { dynamicFetch } from '@/services/form.service'
|
import { dynamicFetch } from '@/services/form.service'
|
||||||
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
|
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
|
||||||
import CustomStore from 'devextreme/data/custom_store'
|
import CustomStore from 'devextreme/data/custom_store'
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
|
|
||||||
|
/** Module-scope cache: key -> Promise<array>
|
||||||
|
* - Aynı anda açılan editörler tek ağ çağrısı üzerinden paylaşır
|
||||||
|
* - Hata olursa cache temizlenir (yeniden denenebilir)
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
const createLookupStaticDataSource = (
|
const createLookupStaticDataSource = (
|
||||||
load: () => any,
|
load: () => any,
|
||||||
filter: any = null,
|
filter: any = null,
|
||||||
key: any = 'key',
|
key: any = 'static',
|
||||||
sort: any = 'name',
|
sort: any = 'name',
|
||||||
) => ({
|
) => ({
|
||||||
store: new CustomStore({
|
store: new CustomStore({
|
||||||
key,
|
key,
|
||||||
loadMode: 'raw',
|
loadMode: 'raw',
|
||||||
load,
|
load: async () => {
|
||||||
|
const cacheKey = `static:${key}`
|
||||||
|
return cachedLoader(cacheKey, async () => {
|
||||||
|
const res = await Promise.resolve(load())
|
||||||
|
return Array.isArray(res) ? res : [res]
|
||||||
|
})
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
sort,
|
sort,
|
||||||
filter,
|
filter,
|
||||||
|
|
@ -30,21 +56,21 @@ const createLookupQueryDataSource = (
|
||||||
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
|
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
|
const cacheKey = `query:${listFormCode}:${listFormFieldName}:${JSON.stringify(filters ?? null)}`
|
||||||
|
return cachedLoader(cacheKey, async () => {
|
||||||
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
|
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
|
||||||
listFormCode,
|
listFormCode,
|
||||||
listFormFieldName,
|
listFormFieldName,
|
||||||
filters,
|
filters,
|
||||||
})
|
})
|
||||||
|
const data = response?.data ?? []
|
||||||
return response.data.map((a: any) => ({
|
return (Array.isArray(data) ? data : [data]).map((a: any) => ({
|
||||||
key: a.Key,
|
key: a.Key,
|
||||||
name: a.Name,
|
name: a.Name,
|
||||||
group: a.Group,
|
group: a.Group,
|
||||||
}))
|
}))
|
||||||
} catch (error: any) {
|
}).catch(() => null as any)
|
||||||
return null
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -67,33 +93,35 @@ const createLookupApiDataSource = (
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const [method, url, body, keySelector, nameSelector, groupSelector] = lookupQuery.split(';')
|
const parts = lookupQuery.split(';')
|
||||||
|
const [
|
||||||
|
method = 'GET',
|
||||||
|
url = '',
|
||||||
|
bodyTemplate = '',
|
||||||
|
keySelector = 'a=>a.id',
|
||||||
|
nameSelector = 'a=>a.name',
|
||||||
|
groupSelector = 'a=>a.group',
|
||||||
|
] = parts
|
||||||
|
|
||||||
|
let resolvedBody = bodyTemplate ?? ''
|
||||||
if (filters?.length) {
|
if (filters?.length) {
|
||||||
for (let i = 0; i < filters.length; i++) {
|
for (let i = 0; i < filters.length; i++) {
|
||||||
body.replace(`@param${i}`, filters[i])
|
resolvedBody = resolvedBody.replace(new RegExp(`@param${i}`, 'g'), String(filters[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const cacheKey = `api:${lookupQuery}:${JSON.stringify(filters ?? null)}`
|
||||||
const response = await dynamicFetch(url, method, null, body)
|
return cachedLoader(cacheKey, async () => {
|
||||||
|
const response = await dynamicFetch(url, method, null, resolvedBody)
|
||||||
let { data } = response
|
let { data } = response
|
||||||
if (!data) {
|
if (!data) return []
|
||||||
return
|
if (!Array.isArray(data)) data = [data]
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(data)) {
|
|
||||||
data = [data]
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.map((a: any) => ({
|
return data.map((a: any) => ({
|
||||||
key: eval(keySelector),
|
key: eval(keySelector),
|
||||||
name: eval(nameSelector),
|
name: eval(nameSelector),
|
||||||
group: eval(groupSelector),
|
group: eval(groupSelector),
|
||||||
}))
|
}))
|
||||||
} catch {
|
}).catch(() => [] as any)
|
||||||
return
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -108,13 +136,11 @@ export const useLookupDataSource = ({
|
||||||
const getLookupDataSource = useCallback(
|
const getLookupDataSource = useCallback(
|
||||||
(options: any, colData: any, data: any) => {
|
(options: any, colData: any, data: any) => {
|
||||||
const { lookupDto } = colData
|
const { lookupDto } = colData
|
||||||
const filters = []
|
const filters: any[] = []
|
||||||
|
|
||||||
//Eğer cascadeParentFields varsa ve data yoksa boş döneriz.
|
// Eğer cascadeParentFields varsa ve row verisi (data) yoksa boş döneriz
|
||||||
if (lookupDto.cascadeParentFields && !data) {
|
if (lookupDto.cascadeParentFields && !data) {
|
||||||
return {
|
return { store: [] }
|
||||||
store: [],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookupDto.cascadeParentFields) {
|
if (lookupDto.cascadeParentFields) {
|
||||||
|
|
@ -132,9 +158,11 @@ export const useLookupDataSource = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
|
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
|
||||||
|
const staticKey = `static:${listFormCode}:${colData.fieldName}`
|
||||||
return createLookupStaticDataSource(
|
return createLookupStaticDataSource(
|
||||||
() => JSON.parse(lookupDto?.lookupQuery),
|
() => JSON.parse(lookupDto?.lookupQuery),
|
||||||
filters.length ? filters : null,
|
filters.length ? filters : null,
|
||||||
|
staticKey,
|
||||||
)
|
)
|
||||||
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
|
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
|
||||||
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters, isSubForm)
|
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters, isSubForm)
|
||||||
|
|
@ -147,9 +175,7 @@ export const useLookupDataSource = ({
|
||||||
isSubForm,
|
isSubForm,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return {
|
return { store: [] }
|
||||||
store: [],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[listFormCode, isSubForm],
|
[listFormCode, isSubForm],
|
||||||
|
|
@ -157,3 +183,9 @@ export const useLookupDataSource = ({
|
||||||
|
|
||||||
return { getLookupDataSource }
|
return { getLookupDataSource }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Opsiyonel: dışarıdan cache temizlemek istersen export et */
|
||||||
|
export const clearLookupCache = (key?: string) => {
|
||||||
|
if (!key) __lookupCache.clear()
|
||||||
|
else __lookupCache.delete(key)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,182 +1,19 @@
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models'
|
import { GridDto } from '@/proxy/form/models'
|
||||||
import { captionize } from 'devextreme/core/utils/inflector'
|
|
||||||
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
|
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
|
||||||
import { Button, Pagination, Select } from '@/components/ui'
|
import { Button, Pagination, Select } from '@/components/ui'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { FaCog, FaSearch } from 'react-icons/fa'
|
import { FaCog, FaSearch } from 'react-icons/fa'
|
||||||
import FormDevExpress from '../form/FormDevExpress'
|
|
||||||
import { GroupItem } from 'devextreme/ui/form'
|
|
||||||
import { Form as FormDx } from 'devextreme-react/form'
|
|
||||||
import FormButtons from '../form/FormButtons'
|
|
||||||
import { useNavigate } from 'react-router-dom'
|
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import CustomStore from 'devextreme/data/custom_store'
|
import CustomStore from 'devextreme/data/custom_store'
|
||||||
import { PermissionResults, SimpleItemWithColData } from '../form/types'
|
|
||||||
import { usePermission } from '@/utils/hooks/usePermission'
|
import { usePermission } from '@/utils/hooks/usePermission'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
import { useLookupDataSource } from '../form/useLookupDataSource'
|
import { useLookupDataSource } from '../form/useLookupDataSource'
|
||||||
import { Container, Loading } from '@/components/shared'
|
import { Container, Loading } from '@/components/shared'
|
||||||
import WidgetGroup from '@/components/common/WidgetGroup'
|
import WidgetGroup from '@/components/common/WidgetGroup'
|
||||||
import { GridExtraFilterState } from './Utils'
|
import { GridExtraFilterState } from './Utils'
|
||||||
import { useStoreActions, useStoreState } from '@/store/store'
|
import { useStoreActions, useStoreState } from '@/store/store'
|
||||||
import { usePWA } from '@/utils/hooks/usePWA'
|
import { usePWA } from '@/utils/hooks/usePWA'
|
||||||
|
import CardItem from './CardItem'
|
||||||
const CardItem = ({
|
|
||||||
isSubForm,
|
|
||||||
row,
|
|
||||||
gridDto,
|
|
||||||
listFormCode,
|
|
||||||
dataSource,
|
|
||||||
refreshData,
|
|
||||||
getCachedLookupDataSource,
|
|
||||||
}: {
|
|
||||||
isSubForm?: boolean
|
|
||||||
row: any
|
|
||||||
gridDto: GridDto
|
|
||||||
listFormCode: string
|
|
||||||
dataSource: CustomStore
|
|
||||||
refreshData: () => void
|
|
||||||
getCachedLookupDataSource: (editorOptions: any, colData: any, row?: any) => any
|
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState(row)
|
|
||||||
const refForm = useRef<FormDx>(null)
|
|
||||||
const navigate = useNavigate()
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
const { checkPermission } = usePermission()
|
|
||||||
const isPwaMode = usePWA()
|
|
||||||
|
|
||||||
const keyField = gridDto.gridOptions.keyFieldName
|
|
||||||
const rowId = row[keyField!]
|
|
||||||
|
|
||||||
// Form Items
|
|
||||||
const formItems: GroupItem[] = useMemo(() => {
|
|
||||||
if (!gridDto) return []
|
|
||||||
|
|
||||||
return gridDto.gridOptions.editingFormDto
|
|
||||||
?.sort((a, b) => (a.order >= b.order ? 1 : -1))
|
|
||||||
.map((e) => {
|
|
||||||
return {
|
|
||||||
itemType: e.itemType,
|
|
||||||
colCount: e.colCount,
|
|
||||||
colSpan: e.colSpan,
|
|
||||||
caption: e.caption,
|
|
||||||
items: e.items
|
|
||||||
?.sort((a, b) => (a.order >= b.order ? 1 : -1))
|
|
||||||
.map((i: EditingFormItemDto) => {
|
|
||||||
let editorOptions = {}
|
|
||||||
const colData = gridDto.columnFormats.find((x) => x.fieldName === i.dataField)
|
|
||||||
|
|
||||||
try {
|
|
||||||
editorOptions = i.editorOptions && JSON.parse(i.editorOptions)
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
const item: SimpleItemWithColData = {
|
|
||||||
canRead: colData?.canRead ?? false,
|
|
||||||
canUpdate: colData?.canUpdate ?? false,
|
|
||||||
canCreate: colData?.canCreate ?? false,
|
|
||||||
canExport: colData?.canExport ?? false,
|
|
||||||
dataField: i.dataField,
|
|
||||||
name: i.dataField,
|
|
||||||
editorType2: i.editorType2,
|
|
||||||
editorType:
|
|
||||||
i.editorType2 == PlatformEditorTypes.dxGridBox ? 'dxDropDownBox' : i.editorType2,
|
|
||||||
colSpan: i.colSpan,
|
|
||||||
isRequired: i.isRequired,
|
|
||||||
editorOptions: {
|
|
||||||
...editorOptions,
|
|
||||||
...(colData?.lookupDto?.dataSourceType
|
|
||||||
? {
|
|
||||||
dataSource: getCachedLookupDataSource(colData?.editorOptions, colData),
|
|
||||||
valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(),
|
|
||||||
displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(),
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
},
|
|
||||||
colData,
|
|
||||||
tagBoxOptions: i.tagBoxOptions,
|
|
||||||
gridBoxOptions: i.gridBoxOptions,
|
|
||||||
script: i.script,
|
|
||||||
}
|
|
||||||
if (i.dataField.indexOf(':') >= 0) {
|
|
||||||
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
|
||||||
}
|
|
||||||
item.editorOptions = {
|
|
||||||
...item.editorOptions,
|
|
||||||
readOnly: true,
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
}),
|
|
||||||
} as GroupItem
|
|
||||||
})
|
|
||||||
}, [gridDto, getCachedLookupDataSource])
|
|
||||||
|
|
||||||
const permissionResults: PermissionResults = {
|
|
||||||
c:
|
|
||||||
gridDto?.gridOptions.editingOptionDto.allowAdding === true &&
|
|
||||||
checkPermission(gridDto?.gridOptions.permissionDto.c),
|
|
||||||
r: checkPermission(gridDto?.gridOptions.permissionDto.r),
|
|
||||||
u:
|
|
||||||
gridDto?.gridOptions.editingOptionDto.allowUpdating === true &&
|
|
||||||
checkPermission(gridDto?.gridOptions.permissionDto.u),
|
|
||||||
d:
|
|
||||||
gridDto?.gridOptions.editingOptionDto.allowDeleting === true &&
|
|
||||||
checkPermission(gridDto?.gridOptions.permissionDto.d),
|
|
||||||
e: checkPermission(gridDto?.gridOptions.permissionDto.e),
|
|
||||||
i: checkPermission(gridDto?.gridOptions.permissionDto.i),
|
|
||||||
}
|
|
||||||
|
|
||||||
const onActionEdit = () => {
|
|
||||||
navigate(
|
|
||||||
ROUTES_ENUM.protected.admin.formEdit
|
|
||||||
.replace(':listFormCode', listFormCode)
|
|
||||||
.replace(':id', rowId!),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onActionNew = () => {
|
|
||||||
navigate(ROUTES_ENUM.protected.admin.formNew.replace(':listFormCode', listFormCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="bg-white dark:bg-neutral-800 border dark:border-neutral-700 flex flex-col">
|
|
||||||
<div
|
|
||||||
className={`flex items-center pt-2 px-2 ${isSubForm ? 'justify-end' : 'justify-between'}`}
|
|
||||||
>
|
|
||||||
{!isSubForm && <h3>{translate('::' + gridDto?.gridOptions.title)}</h3>}
|
|
||||||
{permissionResults && (
|
|
||||||
<FormButtons
|
|
||||||
isSubForm={true}
|
|
||||||
mode="view"
|
|
||||||
listFormCode={listFormCode}
|
|
||||||
id={rowId}
|
|
||||||
gridDto={gridDto}
|
|
||||||
commandColumnData={{ buttons: [] }}
|
|
||||||
dataSource={dataSource}
|
|
||||||
permissions={permissionResults}
|
|
||||||
handleSubmit={() => ({})}
|
|
||||||
refreshData={refreshData}
|
|
||||||
getSelectedRowKeys={() => [rowId]}
|
|
||||||
getSelectedRowsData={() => [row]}
|
|
||||||
getFilter={() => null}
|
|
||||||
onActionEdit={onActionEdit}
|
|
||||||
onActionNew={onActionNew}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex-grow">
|
|
||||||
<FormDevExpress
|
|
||||||
mode="view"
|
|
||||||
refForm={refForm}
|
|
||||||
formData={formData}
|
|
||||||
formItems={formItems}
|
|
||||||
setFormData={setFormData}
|
|
||||||
listFormCode={listFormCode}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CardProps {
|
interface CardProps {
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
|
|
@ -218,20 +55,6 @@ const Card = (props: CardProps) => {
|
||||||
searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(),
|
searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(),
|
||||||
)
|
)
|
||||||
|
|
||||||
const lookupCache = useRef<Map<string, any>>(new Map())
|
|
||||||
const getCachedLookupDataSource = useCallback(
|
|
||||||
(editorOptions: any, colData: any, row?: any) => {
|
|
||||||
const key = colData?.fieldName
|
|
||||||
if (!key) return null
|
|
||||||
|
|
||||||
if (!lookupCache.current.has(key)) {
|
|
||||||
lookupCache.current.set(key, getLookupDataSource(editorOptions, colData, row))
|
|
||||||
}
|
|
||||||
return lookupCache.current.get(key)
|
|
||||||
},
|
|
||||||
[getLookupDataSource],
|
|
||||||
)
|
|
||||||
|
|
||||||
const onPageSizeSelect = ({ value }: Option) => {
|
const onPageSizeSelect = ({ value }: Option) => {
|
||||||
setPageSize(value)
|
setPageSize(value)
|
||||||
setCurrentPage(1)
|
setCurrentPage(1)
|
||||||
|
|
@ -499,7 +322,7 @@ const Card = (props: CardProps) => {
|
||||||
listFormCode={listFormCode}
|
listFormCode={listFormCode}
|
||||||
dataSource={gridDataSource}
|
dataSource={gridDataSource}
|
||||||
refreshData={loadData}
|
refreshData={loadData}
|
||||||
getCachedLookupDataSource={getCachedLookupDataSource}
|
getCachedLookupDataSource={getLookupDataSource}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
172
ui/src/views/list/CardItem.tsx
Normal file
172
ui/src/views/list/CardItem.tsx
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
import { EditingFormItemDto, GridDto, PlatformEditorTypes } from "@/proxy/form/models"
|
||||||
|
import { useLocalization } from "@/utils/hooks/useLocalization"
|
||||||
|
import { usePermission } from "@/utils/hooks/usePermission"
|
||||||
|
import { usePWA } from "@/utils/hooks/usePWA"
|
||||||
|
import CustomStore from "devextreme/data/custom_store"
|
||||||
|
import { useMemo, useRef, useState } from "react"
|
||||||
|
import { useNavigate } from "react-router-dom"
|
||||||
|
import { Form as FormDx } from 'devextreme-react/form'
|
||||||
|
import { GroupItem } from 'devextreme/ui/form'
|
||||||
|
import { PermissionResults, SimpleItemWithColData } from "../form/types"
|
||||||
|
import { captionize } from 'devextreme/core/utils/inflector'
|
||||||
|
import { ROUTES_ENUM } from "@/routes/route.constant"
|
||||||
|
import FormButtons from "../form/FormButtons"
|
||||||
|
import FormDevExpress from "../form/FormDevExpress"
|
||||||
|
|
||||||
|
const CardItem = ({
|
||||||
|
isSubForm,
|
||||||
|
row,
|
||||||
|
gridDto,
|
||||||
|
listFormCode,
|
||||||
|
dataSource,
|
||||||
|
refreshData,
|
||||||
|
getCachedLookupDataSource,
|
||||||
|
}: {
|
||||||
|
isSubForm?: boolean
|
||||||
|
row: any
|
||||||
|
gridDto: GridDto
|
||||||
|
listFormCode: string
|
||||||
|
dataSource: CustomStore
|
||||||
|
refreshData: () => void
|
||||||
|
getCachedLookupDataSource: (editorOptions: any, colData: any, row?: any) => any
|
||||||
|
}) => {
|
||||||
|
const [formData, setFormData] = useState(row)
|
||||||
|
const refForm = useRef<FormDx>(null)
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const { translate } = useLocalization()
|
||||||
|
const { checkPermission } = usePermission()
|
||||||
|
const isPwaMode = usePWA()
|
||||||
|
|
||||||
|
const keyField = gridDto.gridOptions.keyFieldName
|
||||||
|
const rowId = row[keyField!]
|
||||||
|
|
||||||
|
// Form Items
|
||||||
|
const formItems: GroupItem[] = useMemo(() => {
|
||||||
|
if (!gridDto) return []
|
||||||
|
|
||||||
|
return gridDto.gridOptions.editingFormDto
|
||||||
|
?.sort((a, b) => (a.order >= b.order ? 1 : -1))
|
||||||
|
.map((e) => {
|
||||||
|
return {
|
||||||
|
itemType: e.itemType,
|
||||||
|
colCount: e.colCount,
|
||||||
|
colSpan: e.colSpan,
|
||||||
|
caption: e.caption,
|
||||||
|
items: e.items
|
||||||
|
?.sort((a, b) => (a.order >= b.order ? 1 : -1))
|
||||||
|
.map((i: EditingFormItemDto) => {
|
||||||
|
let editorOptions = {}
|
||||||
|
const colData = gridDto.columnFormats.find((x) => x.fieldName === i.dataField)
|
||||||
|
|
||||||
|
try {
|
||||||
|
editorOptions = i.editorOptions && JSON.parse(i.editorOptions)
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
const item: SimpleItemWithColData = {
|
||||||
|
canRead: colData?.canRead ?? false,
|
||||||
|
canUpdate: colData?.canUpdate ?? false,
|
||||||
|
canCreate: colData?.canCreate ?? false,
|
||||||
|
canExport: colData?.canExport ?? false,
|
||||||
|
dataField: i.dataField,
|
||||||
|
name: i.dataField,
|
||||||
|
editorType2: i.editorType2,
|
||||||
|
editorType:
|
||||||
|
i.editorType2 == PlatformEditorTypes.dxGridBox ? 'dxDropDownBox' : i.editorType2,
|
||||||
|
colSpan: i.colSpan,
|
||||||
|
isRequired: i.isRequired,
|
||||||
|
editorOptions: {
|
||||||
|
...editorOptions,
|
||||||
|
...(colData?.lookupDto?.dataSourceType
|
||||||
|
? {
|
||||||
|
dataSource: getCachedLookupDataSource(colData?.editorOptions, colData),
|
||||||
|
valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(),
|
||||||
|
displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
colData,
|
||||||
|
tagBoxOptions: i.tagBoxOptions,
|
||||||
|
gridBoxOptions: i.gridBoxOptions,
|
||||||
|
editorScript: i.editorScript,
|
||||||
|
}
|
||||||
|
if (i.dataField.indexOf(':') >= 0) {
|
||||||
|
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
||||||
|
}
|
||||||
|
item.editorOptions = {
|
||||||
|
...item.editorOptions,
|
||||||
|
readOnly: true,
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}),
|
||||||
|
} as GroupItem
|
||||||
|
})
|
||||||
|
}, [gridDto, getCachedLookupDataSource])
|
||||||
|
|
||||||
|
const permissionResults: PermissionResults = {
|
||||||
|
c:
|
||||||
|
gridDto?.gridOptions.editingOptionDto.allowAdding === true &&
|
||||||
|
checkPermission(gridDto?.gridOptions.permissionDto.c),
|
||||||
|
r: checkPermission(gridDto?.gridOptions.permissionDto.r),
|
||||||
|
u:
|
||||||
|
gridDto?.gridOptions.editingOptionDto.allowUpdating === true &&
|
||||||
|
checkPermission(gridDto?.gridOptions.permissionDto.u),
|
||||||
|
d:
|
||||||
|
gridDto?.gridOptions.editingOptionDto.allowDeleting === true &&
|
||||||
|
checkPermission(gridDto?.gridOptions.permissionDto.d),
|
||||||
|
e: checkPermission(gridDto?.gridOptions.permissionDto.e),
|
||||||
|
i: checkPermission(gridDto?.gridOptions.permissionDto.i),
|
||||||
|
}
|
||||||
|
|
||||||
|
const onActionEdit = () => {
|
||||||
|
navigate(
|
||||||
|
ROUTES_ENUM.protected.admin.formEdit
|
||||||
|
.replace(':listFormCode', listFormCode)
|
||||||
|
.replace(':id', rowId!),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onActionNew = () => {
|
||||||
|
navigate(ROUTES_ENUM.protected.admin.formNew.replace(':listFormCode', listFormCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-white dark:bg-neutral-800 border dark:border-neutral-700 flex flex-col">
|
||||||
|
<div
|
||||||
|
className={`flex items-center pt-2 px-2 ${isSubForm ? 'justify-end' : 'justify-between'}`}
|
||||||
|
>
|
||||||
|
{!isSubForm && <h3>{translate('::' + gridDto?.gridOptions.title)}</h3>}
|
||||||
|
{permissionResults && (
|
||||||
|
<FormButtons
|
||||||
|
isSubForm={true}
|
||||||
|
mode="view"
|
||||||
|
listFormCode={listFormCode}
|
||||||
|
id={rowId}
|
||||||
|
gridDto={gridDto}
|
||||||
|
commandColumnData={{ buttons: [] }}
|
||||||
|
dataSource={dataSource}
|
||||||
|
permissions={permissionResults}
|
||||||
|
handleSubmit={() => ({})}
|
||||||
|
refreshData={refreshData}
|
||||||
|
getSelectedRowKeys={() => [rowId]}
|
||||||
|
getSelectedRowsData={() => [row]}
|
||||||
|
getFilter={() => null}
|
||||||
|
onActionEdit={onActionEdit}
|
||||||
|
onActionNew={onActionNew}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex-grow">
|
||||||
|
<FormDevExpress
|
||||||
|
mode="view"
|
||||||
|
refForm={refForm}
|
||||||
|
formData={formData}
|
||||||
|
formItems={formItems}
|
||||||
|
setFormData={setFormData}
|
||||||
|
listFormCode={listFormCode}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CardItem
|
||||||
|
|
@ -718,9 +718,7 @@ const Grid = (props: GridProps) => {
|
||||||
.flatMap((group) => group.items || [])
|
.flatMap((group) => group.items || [])
|
||||||
.find((i) => i.dataField === editor.dataField)
|
.find((i) => i.dataField === editor.dataField)
|
||||||
|
|
||||||
|
if (formItem?.editorScript) {
|
||||||
console.log(formItem?.dataField, formItem?.script)
|
|
||||||
if (formItem?.script) {
|
|
||||||
const prevHandler = editor.editorOptions.onValueChanged // varsa önceki handler'ı sakla
|
const prevHandler = editor.editorOptions.onValueChanged // varsa önceki handler'ı sakla
|
||||||
|
|
||||||
editor.editorOptions.onValueChanged = (e: any) => {
|
editor.editorOptions.onValueChanged = (e: any) => {
|
||||||
|
|
@ -745,7 +743,7 @@ const Grid = (props: GridProps) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eval(formItem.script!)
|
eval(formItem.editorScript!)
|
||||||
//setFormData({ ...formData, Path: e.value, Authority: e.value })
|
//setFormData({ ...formData, Path: e.value, Authority: e.value })
|
||||||
|
|
||||||
// editor.component.cellValue(
|
// editor.component.cellValue(
|
||||||
|
|
@ -822,9 +820,9 @@ const Grid = (props: GridProps) => {
|
||||||
const formItem = gridDto.gridOptions.editingFormDto
|
const formItem = gridDto.gridOptions.editingFormDto
|
||||||
.flatMap((group) => group.items || [])
|
.flatMap((group) => group.items || [])
|
||||||
.find((i) => i.dataField === e.dataField)
|
.find((i) => i.dataField === e.dataField)
|
||||||
if (formItem?.script) {
|
if (formItem?.editorScript) {
|
||||||
try {
|
try {
|
||||||
eval(formItem.script)
|
eval(formItem.editorScript)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Script exec error', err)
|
console.error('Script exec error', err)
|
||||||
}
|
}
|
||||||
|
|
@ -946,7 +944,7 @@ const Grid = (props: GridProps) => {
|
||||||
colSpan: i.colSpan,
|
colSpan: i.colSpan,
|
||||||
isRequired: i.isRequired,
|
isRequired: i.isRequired,
|
||||||
editorOptions,
|
editorOptions,
|
||||||
script: i.script,
|
editorScript: i.editorScript,
|
||||||
}
|
}
|
||||||
if (i.dataField.indexOf(':') >= 0) {
|
if (i.dataField.indexOf(':') >= 0) {
|
||||||
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue