TreeList ve ListForm Layout hatası düzeltildi.
This commit is contained in:
parent
a2632705c7
commit
f3e187644c
26 changed files with 1210 additions and 140 deletions
|
|
@ -149,6 +149,19 @@ public class GridOptionsDto : AuditedEntityDto<Guid>
|
|||
set { PivotOptionJson = JsonSerializer.Serialize(value); }
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string TreeOptionJson { get; set; }
|
||||
public TreeOptionDto TreeOptionDto
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TreeOptionJson))
|
||||
return JsonSerializer.Deserialize<TreeOptionDto>(TreeOptionJson);
|
||||
return new TreeOptionDto();
|
||||
}
|
||||
set { TreeOptionJson = JsonSerializer.Serialize(value); }
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string PagerOptionJson { get; set; }
|
||||
public GridPagerOptionDto PagerOptionDto
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ public class LayoutDto
|
|||
public bool Grid { get; set; } = true;
|
||||
public bool Card { get; set; } = true;
|
||||
public bool Pivot { get; set; } = true;
|
||||
public bool Tree { get; set; } = true;
|
||||
public bool Chart { get; set; } = true;
|
||||
public string DefaultLayout { get; set; } = "grid";
|
||||
public int CardLayoutColumn { get; set; } = 4;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
namespace Kurs.Platform.ListForms;
|
||||
|
||||
/// <summary>
|
||||
/// TreeList için özel ayarları içerir
|
||||
/// </summary>
|
||||
public class TreeOptionDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Parent kaydı belirten field adı (örn: "parentId")
|
||||
/// </summary>
|
||||
public string ParentIdExpr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Alt kayıtların olup olmadığını belirten field adı (opsiyonel)
|
||||
/// </summary>
|
||||
public string HasItemsExpr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Root (en üst) seviyedeki kayıtların parent değeri (genelde null veya 0)
|
||||
/// </summary>
|
||||
public object RootValue { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Başlangıçta açık olacak node'ların ID'leri
|
||||
/// </summary>
|
||||
public object[] ExpandedRowKeys { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Tüm node'ları başlangıçta açık göster
|
||||
/// </summary>
|
||||
public bool AutoExpandAll { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Alt kayıtlar seçildiğinde parent kayıtları da seç (recursive selection)
|
||||
/// </summary>
|
||||
public bool RecursiveSelection { get; set; } = false;
|
||||
}
|
||||
|
|
@ -46,6 +46,7 @@ public class ListFormEditTabs
|
|||
public const string SelectForm = "select";
|
||||
public const string ColumnForm = "column";
|
||||
public const string PivotForm = "pivot";
|
||||
public const string TreeForm = "tree";
|
||||
public const string PagerForm = "pager";
|
||||
public const string StateForm = "state";
|
||||
public const string SubFormJsonRow = "subForm";
|
||||
|
|
|
|||
|
|
@ -146,6 +146,10 @@ public class ListFormsAppService : CrudAppService<
|
|||
{
|
||||
item.PivotOptionJson = JsonSerializer.Serialize(input.PivotOptionDto);
|
||||
}
|
||||
else if (input.EditType == ListFormEditTabs.TreeForm)
|
||||
{
|
||||
item.TreeOptionJson = JsonSerializer.Serialize(input.TreeOptionDto);
|
||||
}
|
||||
else if (input.EditType == ListFormEditTabs.PagerForm)
|
||||
{
|
||||
item.PagerOptionJson = JsonSerializer.Serialize(input.PagerOptionDto);
|
||||
|
|
|
|||
|
|
@ -3943,6 +3943,12 @@
|
|||
"en": "Pivot Settings",
|
||||
"tr": "Pivot Settings"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.TabTree",
|
||||
"en": "Tree",
|
||||
"tr": "Ağaç"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.TabDetails",
|
||||
|
|
@ -4189,6 +4195,12 @@
|
|||
"en": "Pivot Layout",
|
||||
"tr": "Pivot Düzeni"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.DetailsLayoutDto.TreeLayout",
|
||||
"en": "Tree Layout",
|
||||
"tr": "Ağaç Düzeni"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.DetailsLayoutDto.ChartLayout",
|
||||
|
|
@ -5167,6 +5179,36 @@
|
|||
"en": "Visible",
|
||||
"tr": "Görünür"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.ParentIdExpr",
|
||||
"en": "Parent ID Expression",
|
||||
"tr": "Üst Kimlik İfadesi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.RootValue",
|
||||
"en": "Root Value",
|
||||
"tr": "Kök Değer"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.HasItemsExpr",
|
||||
"en": "Has Items Expression",
|
||||
"tr": "Öğeler Var İfadesi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.RecursiveSelection",
|
||||
"en": "Recursive Selection",
|
||||
"tr": "Özyinelemeli Seçim"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.AutoExpandAll",
|
||||
"en": "Auto Expand All",
|
||||
"tr": "Otomatik Tümünü Genişlet"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListFormEdit.GroupingAutoExpandAll",
|
||||
|
|
|
|||
|
|
@ -5,4 +5,6 @@ public static class ListFormTypeEnum
|
|||
public const string List = "List";
|
||||
public const string Form = "Form";
|
||||
public const string Chart = "Chart";
|
||||
public const string Pivot = "Pivot";
|
||||
public const string Tree = "Tree";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ public class ListForm : FullAuditedEntity<Guid>
|
|||
public string DefaultFilter { get; set; } // Her sorgunun sonuna eklenecek default WHERE condition
|
||||
public string ColumnOptionJson { get; set; }
|
||||
public string PivotOptionJson { get; set; }
|
||||
public string TreeOptionJson { get; set; }
|
||||
public string FilterRowJson { get; set; } // Filtre ayarlari, Json olarak tutulur, donus sinifi FilterRowDto
|
||||
public string RowJson { get; set; } // Row ayarları, Json olarak tutulur, donus sinifi FilterRowDto
|
||||
public string HeaderFilterJson { get; set; } // Header filtreleme ayarlari, Json olarak tutulur
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
|||
namespace Kurs.Platform.Migrations
|
||||
{
|
||||
[DbContext(typeof(PlatformDbContext))]
|
||||
[Migration("20251107194939_Initial")]
|
||||
[Migration("20251107212125_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
|
@ -5210,6 +5210,9 @@ namespace Kurs.Platform.Migrations
|
|||
b.Property<string>("TooltipJson")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TreeOptionJson")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("UpdateCommand")
|
||||
.HasColumnType("text");
|
||||
|
||||
|
|
@ -1885,6 +1885,7 @@ namespace Kurs.Platform.Migrations
|
|||
DefaultFilter = table.Column<string>(type: "text", nullable: true),
|
||||
ColumnOptionJson = table.Column<string>(type: "text", nullable: true),
|
||||
PivotOptionJson = table.Column<string>(type: "text", nullable: true),
|
||||
TreeOptionJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
FilterRowJson = table.Column<string>(type: "text", nullable: true),
|
||||
RowJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
HeaderFilterJson = table.Column<string>(type: "text", nullable: true),
|
||||
|
|
@ -5207,6 +5207,9 @@ namespace Kurs.Platform.Migrations
|
|||
b.Property<string>("TooltipJson")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TreeOptionJson")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("UpdateCommand")
|
||||
.HasColumnType("text");
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export const ListFormEditTabs = {
|
|||
SelectForm: 'select',
|
||||
ColumnForm: 'column',
|
||||
PivotForm: 'pivot',
|
||||
TreeForm: 'tree',
|
||||
PagerForm: 'pager',
|
||||
StateForm: 'state',
|
||||
SubForm: 'subForm',
|
||||
|
|
@ -86,6 +87,7 @@ export const tabVisibilityConfig: Record<string, string[]> = {
|
|||
'select',
|
||||
'columns',
|
||||
'pivots',
|
||||
'tree',
|
||||
'pager',
|
||||
'state',
|
||||
'extrafilter',
|
||||
|
|
|
|||
|
|
@ -377,6 +377,15 @@ export interface GridPivotOptionDto {
|
|||
chartCommonSeriesType: SeriesType
|
||||
}
|
||||
|
||||
export interface TreeOptionDto {
|
||||
parentIdExpr?: string
|
||||
hasItemsExpr?: string
|
||||
rootValue?: any
|
||||
expandedRowKeys?: any[]
|
||||
autoExpandAll?: boolean
|
||||
recursiveSelection?: boolean
|
||||
}
|
||||
|
||||
export interface GridEditingDto {
|
||||
mode?: GridsEditMode
|
||||
refreshMode?: GridsEditRefreshMode
|
||||
|
|
@ -472,6 +481,8 @@ export interface GridOptionsDto extends AuditedEntityDto<string> {
|
|||
columnOptionDto: GridColumnOptionDto
|
||||
pivotOptionJson?: string
|
||||
pivotOptionDto: GridPivotOptionDto
|
||||
treeOptionJson?: string
|
||||
treeOptionDto: TreeOptionDto
|
||||
pagerOptionJson?: string
|
||||
pagerOptionDto: GridPagerOptionDto
|
||||
editingOptionJson?: string
|
||||
|
|
@ -800,6 +811,7 @@ export interface LayoutDto {
|
|||
grid: boolean
|
||||
card: boolean
|
||||
pivot: boolean
|
||||
tree: boolean
|
||||
chart: boolean
|
||||
defaultLayout: ListViewLayoutType
|
||||
cardLayoutColumn: number
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ const useListFormColumns = ({
|
|||
gridDto,
|
||||
listFormCode,
|
||||
isSubForm,
|
||||
gridRef,
|
||||
gridRef
|
||||
}: {
|
||||
gridDto?: GridDto
|
||||
listFormCode: string
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@ import { GridOptionsDto } from '../proxy/form/models'
|
|||
import { GridColumnData } from '../views/list/GridColumnData'
|
||||
import { dynamicFetch } from '../services/form.service'
|
||||
import { MULTIVALUE_DELIMITER } from '../constants/app.constant'
|
||||
import { TreeList } from 'devextreme-react'
|
||||
|
||||
const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk
|
||||
|
||||
const useListFormCustomDataSource = ({
|
||||
gridRef,
|
||||
pivotRef,
|
||||
}: {
|
||||
gridRef?: MutableRefObject<DataGrid<any, any> | undefined>
|
||||
pivotRef?: MutableRefObject<PivotGrid | undefined>
|
||||
gridRef:
|
||||
| MutableRefObject<DataGrid<any, any> | undefined>
|
||||
| MutableRefObject<PivotGrid | undefined>
|
||||
| MutableRefObject<TreeList<any, any> | undefined>
|
||||
}) => {
|
||||
const createSelectDataSource = useCallback(
|
||||
(
|
||||
|
|
@ -58,8 +60,15 @@ const useListFormCustomDataSource = ({
|
|||
if (gridRef?.current) {
|
||||
//TODO:
|
||||
}
|
||||
const columns =
|
||||
(gridRef?.current?.instance.option('columns') as GridColumnData[]) ?? cols
|
||||
// Type guard to handle union type for gridRef
|
||||
let columns = cols
|
||||
if (gridRef?.current?.instance) {
|
||||
const instance = gridRef.current.instance as any
|
||||
const instanceColumns = instance.option('columns')
|
||||
if (instanceColumns) {
|
||||
columns = instanceColumns as GridColumnData[]
|
||||
}
|
||||
}
|
||||
// URL'deki filtreyi grid'in mevcut filtrelerinin üzerine uygula
|
||||
if (columns?.length && searchParams) {
|
||||
const filters: (string[] | string)[] = []
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import FormTabWidgets from './FormTabWidgets'
|
|||
import FormTabExtraFilters from './FormTabExtraFilters'
|
||||
import FormTabEditForm from './FormTabEditForm'
|
||||
import FormTabPivots from './FormTabPivots'
|
||||
import FormTabTree from './FormTabTree'
|
||||
import ChartTabAnimation from './ChartTabAnimation'
|
||||
import ChartTabAnnotations from './ChartTabAnnotations'
|
||||
import ChartTabZoomAndPan from './ChartTabZoomAndPan'
|
||||
|
|
@ -232,6 +233,9 @@ const FormEdit = () => {
|
|||
{visibleTabs.includes('pivots') && (
|
||||
<TabNav value="pivots">{translate('::ListForms.ListFormEdit.TabPivots')}</TabNav>
|
||||
)}
|
||||
{visibleTabs.includes('tree') && (
|
||||
<TabNav value="tree">{translate('::ListForms.ListFormEdit.TabTree')}</TabNav>
|
||||
)}
|
||||
{visibleTabs.includes('pager') && (
|
||||
<TabNav value="pager">{translate('::ListForms.ListFormEdit.TabPaging')}</TabNav>
|
||||
)}
|
||||
|
|
@ -355,6 +359,9 @@ const FormEdit = () => {
|
|||
<TabContent value="pivots" className="px-2">
|
||||
<FormTabPivots onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="tree" className="px-2">
|
||||
<FormTabTree onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
<TabContent value="pager" className="px-2">
|
||||
<FormTabPager onSubmit={onSubmit} />
|
||||
</TabContent>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ const schema = Yup.object().shape({
|
|||
grid: Yup.boolean(),
|
||||
card: Yup.boolean(),
|
||||
pivot: Yup.boolean(),
|
||||
chart: Yup.boolean(),
|
||||
tree: Yup.boolean(),
|
||||
defaultLayout: Yup.string(),
|
||||
cardLayoutColumn: Yup.number(),
|
||||
}),
|
||||
|
|
@ -123,57 +125,6 @@ function FormTabDetails(
|
|||
</Field>
|
||||
</FormItem>
|
||||
|
||||
{values.listFormType === 'List' && (
|
||||
<>
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsLayoutDto.DefaultLayout')}
|
||||
invalid={errors.layoutDto?.defaultLayout && touched.layoutDto?.defaultLayout}
|
||||
errorMessage={errors.layoutDto?.defaultLayout}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name="layoutDto.defaultLayout"
|
||||
placeholder={translate(
|
||||
'::ListForms.ListFormEdit.DetailsLayoutDto.DefaultLayout',
|
||||
)}
|
||||
>
|
||||
{({ field, form }: FieldProps<SelectBox>) => (
|
||||
<Select
|
||||
field={field}
|
||||
form={form}
|
||||
isClearable={true}
|
||||
options={listFormDefaultLayoutOptions}
|
||||
value={listFormDefaultLayoutOptions?.filter(
|
||||
(option) => option.value === values.layoutDto.defaultLayout,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsLayoutDto.CardLayoutColumn')}
|
||||
invalid={
|
||||
errors.layoutDto?.cardLayoutColumn && touched.layoutDto?.cardLayoutColumn
|
||||
}
|
||||
errorMessage={errors.layoutDto?.cardLayoutColumn}
|
||||
>
|
||||
<Field
|
||||
type="number"
|
||||
className="w-20"
|
||||
autoComplete="off"
|
||||
name="layoutDto.cardLayoutColumn"
|
||||
placeholder={translate(
|
||||
'::ListForms.ListFormEdit.DetailsLayoutDto.CardLayoutColumn',
|
||||
)}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsTitle')}
|
||||
invalid={errors.title && touched.title}
|
||||
|
|
@ -268,6 +219,57 @@ function FormTabDetails(
|
|||
</FormItem>
|
||||
</div>
|
||||
|
||||
{values.listFormType === 'List' && (
|
||||
<>
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsLayoutDto.DefaultLayout')}
|
||||
invalid={errors.layoutDto?.defaultLayout && touched.layoutDto?.defaultLayout}
|
||||
errorMessage={errors.layoutDto?.defaultLayout}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name="layoutDto.defaultLayout"
|
||||
placeholder={translate(
|
||||
'::ListForms.ListFormEdit.DetailsLayoutDto.DefaultLayout',
|
||||
)}
|
||||
>
|
||||
{({ field, form }: FieldProps<SelectBox>) => (
|
||||
<Select
|
||||
field={field}
|
||||
form={form}
|
||||
isClearable={true}
|
||||
options={listFormDefaultLayoutOptions}
|
||||
value={listFormDefaultLayoutOptions?.filter(
|
||||
(option) => option.value === values.layoutDto.defaultLayout,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsLayoutDto.CardLayoutColumn')}
|
||||
invalid={
|
||||
errors.layoutDto?.cardLayoutColumn && touched.layoutDto?.cardLayoutColumn
|
||||
}
|
||||
errorMessage={errors.layoutDto?.cardLayoutColumn}
|
||||
>
|
||||
<Field
|
||||
type="number"
|
||||
className="w-20"
|
||||
autoComplete="off"
|
||||
name="layoutDto.cardLayoutColumn"
|
||||
placeholder={translate(
|
||||
'::ListForms.ListFormEdit.DetailsLayoutDto.CardLayoutColumn',
|
||||
)}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex gap-2">
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsLayoutDto.GridLayout')}
|
||||
|
|
@ -324,6 +326,20 @@ function FormTabDetails(
|
|||
component={Checkbox}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.DetailsLayoutDto.TreeLayout')}
|
||||
invalid={errors.layoutDto?.tree && touched.layoutDto?.tree}
|
||||
errorMessage={errors.layoutDto?.tree}
|
||||
>
|
||||
<Field
|
||||
className="w-20"
|
||||
autoComplete="off"
|
||||
name="layoutDto.tree"
|
||||
placeholder={translate('::ListForms.ListFormEdit.DetailsLayoutDto.TreeLayout')}
|
||||
component={Checkbox}
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<FormItem
|
||||
|
|
|
|||
180
ui/src/views/admin/listForm/edit/FormTabTree.tsx
Normal file
180
ui/src/views/admin/listForm/edit/FormTabTree.tsx
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
import { Container } from '@/components/shared'
|
||||
import {
|
||||
Button,
|
||||
Notification,
|
||||
Checkbox,
|
||||
FormContainer,
|
||||
FormItem,
|
||||
Input,
|
||||
Select,
|
||||
toast,
|
||||
} from '@/components/ui'
|
||||
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
|
||||
import { useStoreState } from '@/store'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Field, FieldProps, Form, Formik } from 'formik'
|
||||
import * as Yup from 'yup'
|
||||
import { FormEditProps } from './FormEdit'
|
||||
import { SelectBoxOption } from '@/shared/types'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { getListFormFields } from '@/services/admin/list-form-field.service'
|
||||
import { groupBy } from 'lodash'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
const validationSchema = Yup.object().shape({})
|
||||
|
||||
function FormTabTree(props: FormEditProps) {
|
||||
const { listFormCode } = useParams()
|
||||
const { translate } = useLocalization()
|
||||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||
|
||||
const getFields = async () => {
|
||||
if (!listFormCode) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const resp = await getListFormFields({
|
||||
listFormCode,
|
||||
sorting: 'ListOrderNo',
|
||||
maxResultCount: 1000,
|
||||
})
|
||||
if (resp.data?.items) {
|
||||
const fieldNames = groupBy(resp?.data?.items, 'fieldName')
|
||||
setFieldList(
|
||||
Object.keys(fieldNames).map((a) => ({
|
||||
value: a,
|
||||
label: a,
|
||||
})),
|
||||
)
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.push(
|
||||
<Notification type="danger" duration={2000}>
|
||||
Alanlar getirilemedi
|
||||
{error.toString()}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getFields()
|
||||
}, [listFormCode])
|
||||
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
if (!listFormValues) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
<Formik
|
||||
initialValues={listFormValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={async (values, formikHelpers) => {
|
||||
await props.onSubmit(ListFormEditTabs.TreeForm, values, formikHelpers)
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.ParentIdExpr')}
|
||||
invalid={errors.treeOptionDto?.parentIdExpr && touched.treeOptionDto?.parentIdExpr}
|
||||
errorMessage={errors.treeOptionDto?.parentIdExpr}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
name="treeOptionDto.parentIdExpr"
|
||||
placeholder={translate('::ListForms.ListFormEdit.ParentIdExpr')}
|
||||
>
|
||||
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||
<Select
|
||||
field={field}
|
||||
form={form}
|
||||
isClearable={true}
|
||||
options={fieldList}
|
||||
value={fieldList?.filter(
|
||||
(option) => option.value === values.treeOptionDto.parentIdExpr,
|
||||
)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
menuPlacement="auto"
|
||||
maxMenuHeight={150}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.HasItemsExpr')}
|
||||
invalid={errors.treeOptionDto?.hasItemsExpr && touched.treeOptionDto?.hasItemsExpr}
|
||||
errorMessage={errors.treeOptionDto?.hasItemsExpr}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name="treeOptionDto.hasItemsExpr"
|
||||
placeholder={translate('::ListForms.ListFormEdit.HasItemsExpr')}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.RootValue')}
|
||||
invalid={!!(errors.treeOptionDto?.rootValue && touched.treeOptionDto?.rootValue)}
|
||||
errorMessage={errors.treeOptionDto?.rootValue as string}
|
||||
>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name="treeOptionDto.rootValue"
|
||||
placeholder={translate('::ListForms.ListFormEdit.RootValue')}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.AutoExpandAll')}
|
||||
invalid={
|
||||
errors.treeOptionDto?.autoExpandAll && touched.treeOptionDto?.autoExpandAll
|
||||
}
|
||||
errorMessage={errors.treeOptionDto?.autoExpandAll}
|
||||
>
|
||||
<Field
|
||||
name="treeOptionDto.autoExpandAll"
|
||||
placeholder={translate('::ListForms.ListFormEdit.AutoExpandAll')}
|
||||
component={Checkbox}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
label={translate('::ListForms.ListFormEdit.RecursiveSelection')}
|
||||
invalid={
|
||||
errors.treeOptionDto?.recursiveSelection &&
|
||||
touched.treeOptionDto?.recursiveSelection
|
||||
}
|
||||
errorMessage={errors.treeOptionDto?.recursiveSelection}
|
||||
>
|
||||
<Field
|
||||
name="treeOptionDto.recursiveSelection"
|
||||
placeholder={translate('::ListForms.ListFormEdit.RecursiveSelection')}
|
||||
component={Checkbox}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block variant="solid" loading={isSubmitting} type="submit" className="my-2">
|
||||
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default FormTabTree
|
||||
|
|
@ -211,6 +211,7 @@ export const listFormDefaultLayoutOptions = [
|
|||
{ value: 'card', label: 'Card' },
|
||||
{ value: 'pivot', label: 'Pivot' },
|
||||
{ value: 'chart', label: 'Chart' },
|
||||
{ value: 'tree', label: 'Tree' },
|
||||
]
|
||||
|
||||
export const listFormAlignmentOptions = [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export type ChartOperation = '' | 'select' | 'insert' | 'update' | 'delete'
|
||||
export type ChartDialogType = '' | 'pane' | 'serie' | 'annotation' | 'axis'
|
||||
export type ListViewLayoutType = 'grid' | 'card' | 'pivot' | 'chart'
|
||||
export type ListViewLayoutType = 'grid' | 'card' | 'pivot' | 'tree' | 'chart'
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import { Item } from 'devextreme-react/toolbar'
|
|||
import { DataType } from 'devextreme/common'
|
||||
import { captionize } from 'devextreme/core/utils/inflector'
|
||||
import CustomStore from 'devextreme/data/custom_store'
|
||||
import { GroupItem } from 'devextreme/ui/form'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import SubForms from '../form/SubForms'
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useLocation, useParams, useSearchParams } from 'react-router-dom'
|
|||
import { useEffect, useState } from 'react'
|
||||
import Container from '@/components/shared/Container'
|
||||
import Grid from './Grid'
|
||||
import { FaChartArea, FaList, FaTable, FaTh, FaUser } from 'react-icons/fa'
|
||||
import { FaChartArea, FaList, FaSitemap, FaTable, FaTh, FaUser } from 'react-icons/fa'
|
||||
import { useStoreActions, useStoreState } from '@/store/store'
|
||||
import classNames from 'classnames'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -10,6 +10,7 @@ import { GridDto } from '@/proxy/form/models'
|
|||
import Card from './Card'
|
||||
import { Badge, Button } from '@/components/ui'
|
||||
import Pivot from './Pivot'
|
||||
import Tree from './Tree'
|
||||
import { getList } from '@/services/form.service'
|
||||
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
|
||||
import { ListViewLayoutType } from '../admin/listForm/edit/types'
|
||||
|
|
@ -41,17 +42,21 @@ const List = () => {
|
|||
}
|
||||
|
||||
useEffect(() => {
|
||||
refreshGridDto().then(() => {
|
||||
//base içerisine kaydedilen state içerisinden bakılacak
|
||||
const listFormStates = states.find((a) => a.listFormCode === listFormCode)
|
||||
if (listFormStates) {
|
||||
setViewMode(listFormStates.layout || 'grid')
|
||||
} else {
|
||||
setViewMode(gridDto?.gridOptions?.layoutDto.defaultLayout || 'grid')
|
||||
}
|
||||
})
|
||||
refreshGridDto()
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
const listFormStates = states.find((a) => a.listFormCode === listFormCode)
|
||||
|
||||
if (listFormStates) {
|
||||
setViewMode(listFormStates.layout)
|
||||
}
|
||||
|
||||
if (gridDto) {
|
||||
setViewMode(gridDto?.gridOptions?.layoutDto.defaultLayout)
|
||||
}
|
||||
}, [gridDto])
|
||||
|
||||
if (!listFormCode) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -86,6 +91,21 @@ const List = () => {
|
|||
)}
|
||||
|
||||
<div className="flex gap-1">
|
||||
{gridDto?.gridOptions?.layoutDto.tree &&
|
||||
gridDto?.gridOptions?.treeOptionDto?.parentIdExpr && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant={viewMode === 'tree' ? 'solid' : 'default'}
|
||||
onClick={() => {
|
||||
setViewMode('tree')
|
||||
setStates({ listFormCode, layout: 'tree' })
|
||||
}}
|
||||
title="TreeList Görünümü"
|
||||
>
|
||||
<FaSitemap className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{gridDto?.gridOptions?.layoutDto.grid && (
|
||||
<Button
|
||||
size="xs"
|
||||
|
|
@ -152,6 +172,13 @@ const List = () => {
|
|||
gridDto={gridDto}
|
||||
refreshGridDto={refreshGridDto}
|
||||
/>
|
||||
) : viewMode === 'tree' ? (
|
||||
<Tree
|
||||
listFormCode={listFormCode}
|
||||
searchParams={searchParams}
|
||||
isSubForm={false}
|
||||
gridDto={gridDto}
|
||||
/>
|
||||
) : viewMode === 'card' ? (
|
||||
<Card
|
||||
listFormCode={listFormCode}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,7 @@ import {
|
|||
import { useFilters } from './useFilters'
|
||||
import WidgetGroup from '@/components/common/WidgetGroup'
|
||||
import { Button } from '@/components/ui'
|
||||
import {
|
||||
FaCog,
|
||||
FaTimes,
|
||||
FaUndo,
|
||||
} from 'react-icons/fa'
|
||||
import { FaCog, FaTimes, FaUndo } from 'react-icons/fa'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { usePWA } from '@/utils/hooks/usePWA'
|
||||
|
|
@ -74,7 +70,7 @@ const Pivot = (props: PivotProps) => {
|
|||
listFormCode,
|
||||
})
|
||||
|
||||
const { createSelectDataSource } = useListFormCustomDataSource({ pivotRef: gridRef })
|
||||
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
|
||||
const { getBandedColumns } = useListFormColumns({
|
||||
gridDto,
|
||||
listFormCode,
|
||||
|
|
@ -413,56 +409,3 @@ const Pivot = (props: PivotProps) => {
|
|||
}
|
||||
|
||||
export default Pivot
|
||||
|
||||
/*
|
||||
<Toolbar visible={toolbarData.length > 0 || filterToolbarData.length > 0}>
|
||||
{toolbarData.map((item) => (
|
||||
<Item key={item.name} {...item}></Item>
|
||||
))}
|
||||
{filterToolbarData.map((item) => (
|
||||
<Item key={item.name} {...item}></Item>
|
||||
))}
|
||||
</Toolbar>
|
||||
<Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
|
||||
<FilterRow
|
||||
visible={gridDto.gridOptions.filterRowDto?.visible}
|
||||
applyFilter={gridDto.gridOptions.filterRowDto?.applyFilter}
|
||||
></FilterRow>
|
||||
<FilterPanel visible={gridDto.gridOptions.filterPanelDto.visible}></FilterPanel>
|
||||
<HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
|
||||
<SearchPanel
|
||||
visible={gridDto.gridOptions.searchPanelDto.visible}
|
||||
width={gridDto.gridOptions.searchPanelDto.width}
|
||||
></SearchPanel>
|
||||
<GroupPanel visible={gridDto.gridOptions.groupPanelDto?.visible}></GroupPanel>
|
||||
<Grouping autoExpandAll={gridDto.gridOptions.groupPanelDto?.autoExpandAll}></Grouping>
|
||||
<Selection
|
||||
mode={gridDto.gridOptions.selectionDto?.mode}
|
||||
allowSelectAll={gridDto.gridOptions.selectionDto?.allowSelectAll}
|
||||
selectAllMode={gridDto.gridOptions.selectionDto?.selectAllMode}
|
||||
showCheckBoxesMode={gridDto.gridOptions.selectionDto?.showCheckBoxesMode}
|
||||
></Selection>
|
||||
<Pager
|
||||
visible={gridDto.gridOptions.pagerOptionDto?.visible}
|
||||
allowedPageSizes={gridDto.gridOptions.pagerOptionDto?.allowedPageSizes
|
||||
?.split(',')
|
||||
.map((a) => +a)}
|
||||
showPageSizeSelector={gridDto.gridOptions.pagerOptionDto?.showPageSizeSelector}
|
||||
showInfo={gridDto.gridOptions.pagerOptionDto?.showInfo}
|
||||
showNavigationButtons={gridDto.gridOptions.pagerOptionDto?.showNavigationButtons}
|
||||
infoText={gridDto.gridOptions.pagerOptionDto?.infoText}
|
||||
displayMode={gridDto.gridOptions.pagerOptionDto?.displayMode}
|
||||
></Pager>
|
||||
<ColumnChooser
|
||||
enabled={gridDto.gridOptions.columnOptionDto?.columnChooserEnabled}
|
||||
mode={gridDto.gridOptions.columnOptionDto?.columnChooserMode}
|
||||
></ColumnChooser>
|
||||
<ColumnFixing
|
||||
enabled={gridDto.gridOptions.columnOptionDto?.columnFixingEnabled}
|
||||
></ColumnFixing>
|
||||
<Scrolling mode={gridDto.gridOptions.pagerOptionDto?.scrollingMode}></Scrolling>
|
||||
<LoadPanel
|
||||
enabled={gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled}
|
||||
text={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
|
||||
></LoadPanel>
|
||||
*/
|
||||
|
|
|
|||
715
ui/src/views/list/Tree.tsx
Normal file
715
ui/src/views/list/Tree.tsx
Normal file
|
|
@ -0,0 +1,715 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import Container from '@/components/shared/Container'
|
||||
import { Dialog, Notification, toast } from '@/components/ui'
|
||||
import { DX_CLASSNAMES } from '@/constants/app.constant'
|
||||
import { GridDto, ListFormCustomizationTypeEnum } from '@/proxy/form/models'
|
||||
import {
|
||||
getListFormCustomization,
|
||||
postListFormCustomization,
|
||||
} from '@/services/list-form-customization.service'
|
||||
import { useListFormColumns } from '@/shared/useListFormColumns'
|
||||
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import useResponsive from '@/utils/hooks/useResponsive'
|
||||
import { Template } from 'devextreme-react/core/template'
|
||||
import TreeListDx, {
|
||||
ColumnChooser,
|
||||
ColumnFixing,
|
||||
Editing,
|
||||
FilterPanel,
|
||||
FilterRow,
|
||||
HeaderFilter,
|
||||
IStateStoringProps,
|
||||
LoadPanel,
|
||||
Pager,
|
||||
RemoteOperations,
|
||||
Scrolling,
|
||||
SearchPanel,
|
||||
Selection,
|
||||
Sorting,
|
||||
StateStoring,
|
||||
TreeListTypes,
|
||||
} from 'devextreme-react/tree-list'
|
||||
import { Item, Toolbar } from 'devextreme-react/toolbar'
|
||||
import CustomStore from 'devextreme/data/custom_store'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { RowMode } from '../form/types'
|
||||
import { GridColumnData } from './GridColumnData'
|
||||
import GridFilterDialogs from './GridFilterDialogs'
|
||||
import {
|
||||
addCss,
|
||||
addJs,
|
||||
controlStyleCondition,
|
||||
GridExtraFilterState,
|
||||
setFormEditingExtraItemValues,
|
||||
setGridPanelColor,
|
||||
} from './Utils'
|
||||
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
|
||||
import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent'
|
||||
import { useFilters } from './useFilters'
|
||||
import { useToolbar } from './useToolbar'
|
||||
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
|
||||
import { GridExtraFilterToolbar } from './GridExtraFilterToolbar'
|
||||
import { getList } from '@/services/form.service'
|
||||
|
||||
interface TreeProps {
|
||||
listFormCode: string
|
||||
searchParams?: URLSearchParams
|
||||
isSubForm?: boolean
|
||||
level?: number
|
||||
refreshData?: () => Promise<void>
|
||||
gridDto?: GridDto
|
||||
}
|
||||
|
||||
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)'
|
||||
|
||||
const Tree = (props: TreeProps) => {
|
||||
const { listFormCode, searchParams, isSubForm, level, gridDto: extGridDto } = props
|
||||
const { translate } = useLocalization()
|
||||
const { smaller } = useResponsive()
|
||||
|
||||
const gridRef = useRef<TreeListDx>()
|
||||
const refListFormCode = useRef('')
|
||||
|
||||
const [treeListDataSource, setTreeListDataSource] = useState<CustomStore<any, any>>()
|
||||
const [columnData, setColumnData] = useState<GridColumnData[]>()
|
||||
const [formData, setFormData] = useState<any>()
|
||||
const [mode, setMode] = useState<RowMode>('view')
|
||||
const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])
|
||||
const [gridDto, setGridDto] = useState<GridDto>()
|
||||
const [isPopupFullScreen, setIsPopupFullScreen] = useState(false)
|
||||
const [expandedRowKeys, setExpandedRowKeys] = useState<any[]>([])
|
||||
|
||||
const defaultSearchParams = useRef<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const initializeTreeList = async () => {
|
||||
const response = await getList({ listFormCode })
|
||||
setGridDto(response.data)
|
||||
}
|
||||
|
||||
if (extGridDto === undefined) {
|
||||
initializeTreeList()
|
||||
} else {
|
||||
setGridDto(extGridDto)
|
||||
}
|
||||
}, [listFormCode, extGridDto])
|
||||
|
||||
useEffect(() => {
|
||||
if (!defaultSearchParams.current) {
|
||||
defaultSearchParams.current = searchParams?.get('filter') ?? null
|
||||
}
|
||||
}, [searchParams])
|
||||
|
||||
const { toolbarData, toolbarModalData, setToolbarModalData } = useToolbar({
|
||||
gridDto,
|
||||
listFormCode,
|
||||
getSelectedRowKeys,
|
||||
getSelectedRowsData,
|
||||
refreshData,
|
||||
getFilter,
|
||||
})
|
||||
|
||||
const { filterToolbarData, ...filterData } = useFilters({
|
||||
gridDto,
|
||||
gridRef,
|
||||
listFormCode,
|
||||
})
|
||||
|
||||
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
|
||||
const { getBandedColumns } = useListFormColumns({
|
||||
gridDto,
|
||||
listFormCode,
|
||||
isSubForm,
|
||||
gridRef,
|
||||
})
|
||||
|
||||
function extractSearchParamsFields(filter: any): [string, string, any][] {
|
||||
if (!Array.isArray(filter)) return []
|
||||
|
||||
if (filter.length === 3 && typeof filter[0] === 'string') {
|
||||
return [filter as [string, string, any]]
|
||||
}
|
||||
|
||||
return filter.flatMap((f) => extractSearchParamsFields(f))
|
||||
}
|
||||
|
||||
async function getSelectedRowKeys() {
|
||||
const tree = gridRef.current?.instance
|
||||
if (!tree) {
|
||||
return []
|
||||
}
|
||||
|
||||
return await tree.getSelectedRowKeys()
|
||||
}
|
||||
|
||||
function getSelectedRowsData() {
|
||||
const tree = gridRef.current?.instance
|
||||
if (!tree) {
|
||||
return []
|
||||
}
|
||||
|
||||
return tree.getSelectedRowsData()
|
||||
}
|
||||
|
||||
function refreshData() {
|
||||
gridRef.current?.instance.refresh()
|
||||
}
|
||||
|
||||
function getFilter() {
|
||||
const tree = gridRef.current?.instance
|
||||
if (!tree) {
|
||||
return
|
||||
}
|
||||
|
||||
return tree.getCombinedFilter()
|
||||
}
|
||||
|
||||
function onSelectionChanged(data: any) {
|
||||
const treeOpt = gridDto?.gridOptions
|
||||
const tree = gridRef.current?.instance
|
||||
if (!treeOpt || !tree) {
|
||||
return
|
||||
}
|
||||
|
||||
if (treeOpt.editingOptionDto?.allowDeleting) {
|
||||
try {
|
||||
const opt = tree.option('toolbar')
|
||||
if (opt && opt.items && Array.isArray(opt.items)) {
|
||||
const deleteSelectedRecordsIndex = opt.items
|
||||
.map((e: any) => e.name)
|
||||
.indexOf('deleteSelectedRecords')
|
||||
|
||||
if (deleteSelectedRecordsIndex >= 0) {
|
||||
tree.option(
|
||||
`toolbar.items[${deleteSelectedRecordsIndex}].options.visible`,
|
||||
data.selectedRowsData.length > 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error updating toolbar items:', error)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.selectedRowsData.length) {
|
||||
setFormData(data.selectedRowsData[0])
|
||||
}
|
||||
}
|
||||
|
||||
function onCellPrepared(e: any) {
|
||||
const columnFormats = gridDto?.columnFormats
|
||||
if (!columnFormats) {
|
||||
return
|
||||
}
|
||||
|
||||
for (let indxCol = 0; indxCol < columnFormats.length; indxCol++) {
|
||||
const colFormat = columnFormats[indxCol]
|
||||
for (let indxStyl = 0; indxStyl < colFormat.columnStylingDto.length; indxStyl++) {
|
||||
const colStyle = colFormat.columnStylingDto[indxStyl]
|
||||
if (e.rowType == colStyle.rowType) {
|
||||
if (colStyle.useRow || e.column.dataField == colFormat.fieldName) {
|
||||
if (
|
||||
!colStyle.conditionValue ||
|
||||
controlStyleCondition(e.data, colFormat.fieldName, colStyle)
|
||||
) {
|
||||
if (colStyle.cssClassName) {
|
||||
e.cellElement.addClass(colStyle.cssClassName)
|
||||
}
|
||||
if (colStyle.cssStyles) {
|
||||
e.cellElement.attr('style', e.cellElement.attr('style') + ';' + colStyle.cssStyles)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onInitNewRow(e: any) {
|
||||
if (!gridDto?.columnFormats) {
|
||||
return
|
||||
}
|
||||
|
||||
setMode('new')
|
||||
setIsPopupFullScreen(gridDto?.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)
|
||||
|
||||
for (const colFormat of gridDto?.columnFormats) {
|
||||
if (!colFormat.fieldName) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (colFormat.defaultValue != null) {
|
||||
e.data[colFormat.fieldName] = colFormat.defaultValue
|
||||
}
|
||||
|
||||
if (extraFilters.some((f) => f.fieldName === colFormat.fieldName)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (!searchParams) {
|
||||
continue
|
||||
}
|
||||
|
||||
const rawFilter = searchParams?.get('filter')
|
||||
if (rawFilter) {
|
||||
const parsed = JSON.parse(rawFilter)
|
||||
const filters = extractSearchParamsFields(parsed)
|
||||
|
||||
const hasFilter = filters.some(([field, op, val]) => field === colFormat.fieldName)
|
||||
|
||||
if (hasFilter) {
|
||||
const fieldMatch = filters.find(([field, op, val]) => field === colFormat.fieldName)
|
||||
|
||||
if (fieldMatch) {
|
||||
const [, , val] = fieldMatch
|
||||
const dType = colFormat.dataType as any
|
||||
|
||||
switch (dType) {
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
e.data[colFormat.fieldName] = new Date(val)
|
||||
break
|
||||
case 'number':
|
||||
e.data[colFormat.fieldName] = Number(val)
|
||||
break
|
||||
case 'boolean':
|
||||
e.data[colFormat.fieldName] = val === true || val === 'true'
|
||||
break
|
||||
case 'object':
|
||||
try {
|
||||
e.data[colFormat.fieldName] = JSON.parse(val)
|
||||
} catch {}
|
||||
break
|
||||
default:
|
||||
e.data[colFormat.fieldName] = val
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onRowInserting(e: TreeListTypes.RowInsertingEvent) {
|
||||
e.data = setFormEditingExtraItemValues(e.data)
|
||||
}
|
||||
|
||||
function onRowUpdating(e: TreeListTypes.RowUpdatingEvent) {
|
||||
if (gridDto?.gridOptions.editingOptionDto?.sendOnlyChangedFormValuesUpdate) {
|
||||
if (Object.keys(e.newData).some((a) => a.includes(':'))) {
|
||||
Object.keys(e.oldData).forEach((col) => {
|
||||
if (col.includes(':')) {
|
||||
e.newData[col] = e.newData[col] ?? e.oldData[col]
|
||||
}
|
||||
})
|
||||
}
|
||||
e.newData = setFormEditingExtraItemValues(e.newData)
|
||||
} else {
|
||||
let newData = { ...e.oldData, ...e.newData }
|
||||
newData = setFormEditingExtraItemValues(newData)
|
||||
Object.keys(newData).forEach((key) => {
|
||||
if (key.includes(':')) {
|
||||
delete newData[key]
|
||||
}
|
||||
})
|
||||
e.newData = newData
|
||||
}
|
||||
|
||||
if (gridDto?.gridOptions.keyFieldName) {
|
||||
delete e.newData[gridDto?.gridOptions.keyFieldName]
|
||||
}
|
||||
}
|
||||
|
||||
function onEditingStart(e: TreeListTypes.EditingStartEvent) {
|
||||
setMode('edit')
|
||||
setIsPopupFullScreen(gridDto?.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)
|
||||
const columns = e.component.option('columns') as GridColumnData[]
|
||||
columns?.forEach((col) => {
|
||||
if (!col.dataField?.includes(':')) {
|
||||
return
|
||||
}
|
||||
const field = col.dataField.split(':')
|
||||
if (!e.data[field[0]]) {
|
||||
return
|
||||
}
|
||||
const json = JSON.parse(e.data[field[0]])
|
||||
e.data[col.dataField] = json[field[1]]
|
||||
})
|
||||
}
|
||||
|
||||
function onDataErrorOccurred(e: TreeListTypes.DataErrorOccurredEvent) {
|
||||
toast.push(
|
||||
<Notification type="danger" duration={2000}>
|
||||
{e.error?.message}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const customSaveState = useCallback(
|
||||
(state: any) =>
|
||||
postListFormCustomization({
|
||||
listFormCode: listFormCode,
|
||||
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||
filterName: `tree-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`,
|
||||
customizationData: JSON.stringify(state),
|
||||
}).then(() => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
}),
|
||||
[listFormCode],
|
||||
)
|
||||
|
||||
const customLoadState = useCallback(
|
||||
() =>
|
||||
getListFormCustomization(
|
||||
listFormCode,
|
||||
ListFormCustomizationTypeEnum.GridState,
|
||||
`tree-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`,
|
||||
).then((response: any) => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
if (response.data?.length > 0) {
|
||||
return JSON.parse(response.data[0].customizationData)
|
||||
}
|
||||
}),
|
||||
[listFormCode],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (gridRef?.current) {
|
||||
gridRef.current.instance.option('columns', undefined)
|
||||
gridRef.current.instance.option('dataSource', undefined)
|
||||
gridRef.current.instance.state(null)
|
||||
}
|
||||
|
||||
if (refListFormCode.current !== listFormCode) {
|
||||
setExtraFilters([])
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
useEffect(() => {
|
||||
if (!gridDto) {
|
||||
return
|
||||
}
|
||||
|
||||
const treeOpt = gridDto.gridOptions
|
||||
if (treeOpt.customJsSources.length) {
|
||||
for (const js of treeOpt.customJsSources) {
|
||||
addJs(js)
|
||||
}
|
||||
}
|
||||
if (treeOpt.customStyleSources.length) {
|
||||
for (const css of treeOpt.customStyleSources) {
|
||||
addCss(css)
|
||||
}
|
||||
}
|
||||
|
||||
if (gridDto?.gridOptions.extraFilterDto) {
|
||||
setExtraFilters(
|
||||
gridDto.gridOptions.extraFilterDto.map((f) => ({
|
||||
fieldName: f.fieldName,
|
||||
operator: f.operator,
|
||||
controlType: f.controlType,
|
||||
value: f.defaultValue ?? '',
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
if (gridDto.gridOptions.editingOptionDto?.popup) {
|
||||
setIsPopupFullScreen(gridDto.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)
|
||||
}
|
||||
|
||||
// Set initial expanded row keys
|
||||
if (gridDto.gridOptions.treeOptionDto?.expandedRowKeys) {
|
||||
setExpandedRowKeys(gridDto.gridOptions.treeOptionDto.expandedRowKeys)
|
||||
} else if (gridDto.gridOptions.treeOptionDto?.autoExpandAll) {
|
||||
setExpandedRowKeys([])
|
||||
}
|
||||
}, [gridDto])
|
||||
|
||||
useEffect(() => {
|
||||
if (!gridDto) return
|
||||
|
||||
const cols = getBandedColumns()
|
||||
setColumnData(cols)
|
||||
|
||||
const dataSource = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams, cols)
|
||||
setTreeListDataSource(dataSource)
|
||||
}, [gridDto, searchParams])
|
||||
|
||||
useEffect(() => {
|
||||
const activeFilters = extraFilters.filter((f) => f.value)
|
||||
|
||||
let base: any = null
|
||||
if (defaultSearchParams.current) {
|
||||
base = JSON.parse(defaultSearchParams.current)
|
||||
}
|
||||
|
||||
const baseTriplets = extractSearchParamsFields(base)
|
||||
|
||||
const extraTriplets = activeFilters.map(
|
||||
(f) => [f.fieldName, f.operator, f.value] as [string, string, any],
|
||||
)
|
||||
|
||||
const merged = [...baseTriplets, ...extraTriplets].reduce(
|
||||
(acc, cur) => {
|
||||
const [field, op] = cur
|
||||
const idx = acc.findIndex((a) => a[0] === field && a[1] === op)
|
||||
if (idx >= 0) {
|
||||
acc[idx] = cur
|
||||
} else {
|
||||
acc.push(cur)
|
||||
}
|
||||
return acc
|
||||
},
|
||||
[] as [string, string, any][],
|
||||
)
|
||||
|
||||
let filter: any = null
|
||||
if (merged.length === 1) {
|
||||
filter = merged[0]
|
||||
} else if (merged.length > 1) {
|
||||
filter = merged.reduce((acc, f, idx) => {
|
||||
if (idx === 0) return f
|
||||
return [acc, 'and', f]
|
||||
}, null as any)
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
searchParams?.set('filter', JSON.stringify(filter))
|
||||
} else {
|
||||
searchParams?.delete('filter')
|
||||
}
|
||||
|
||||
gridRef.current?.instance.refresh()
|
||||
}, [extraFilters])
|
||||
|
||||
useEffect(() => {
|
||||
refListFormCode.current = listFormCode
|
||||
if (!gridRef?.current) {
|
||||
return
|
||||
}
|
||||
|
||||
gridRef.current.instance.option('columns', columnData as any)
|
||||
gridRef.current.instance.option('dataSource', treeListDataSource)
|
||||
|
||||
const stateStoring: IStateStoringProps = {
|
||||
enabled: gridDto?.gridOptions.stateStoringDto?.enabled,
|
||||
type: gridDto?.gridOptions.stateStoringDto?.type,
|
||||
savingTimeout: gridDto?.gridOptions.stateStoringDto?.savingTimeout,
|
||||
storageKey: gridDto?.gridOptions.stateStoringDto?.storageKey,
|
||||
}
|
||||
if (
|
||||
gridDto?.gridOptions.stateStoringDto?.enabled &&
|
||||
gridDto?.gridOptions.stateStoringDto?.type === 'custom'
|
||||
) {
|
||||
stateStoring.customSave = customSaveState
|
||||
stateStoring.customLoad = customLoadState
|
||||
}
|
||||
gridRef.current.instance.option('stateStoring', stateStoring)
|
||||
}, [columnData])
|
||||
|
||||
return (
|
||||
<>
|
||||
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
|
||||
|
||||
<Container className={DX_CLASSNAMES}>
|
||||
{!isSubForm && (
|
||||
<Helmet
|
||||
titleTemplate="%s | Erp Platform"
|
||||
title={translate('::' + gridDto?.gridOptions.title)}
|
||||
defaultTitle="Erp Platform"
|
||||
></Helmet>
|
||||
)}
|
||||
{gridDto && columnData && (
|
||||
<div className="p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 ">
|
||||
<TreeListDx
|
||||
ref={gridRef as any}
|
||||
id={'TreeList-' + listFormCode}
|
||||
height={gridDto.gridOptions.height || 'calc(100vh - 150px)'}
|
||||
width={gridDto.gridOptions.width || '100%'}
|
||||
dataStructure="plain"
|
||||
keyExpr={gridDto.gridOptions.keyFieldName}
|
||||
parentIdExpr={gridDto.gridOptions.treeOptionDto?.parentIdExpr || 'parentId'}
|
||||
hasItemsExpr={gridDto.gridOptions.treeOptionDto?.hasItemsExpr}
|
||||
rootValue={
|
||||
gridDto.gridOptions.treeOptionDto?.rootValue === '' ||
|
||||
gridDto.gridOptions.treeOptionDto?.rootValue === undefined
|
||||
? null
|
||||
: gridDto.gridOptions.treeOptionDto?.rootValue
|
||||
}
|
||||
{...(!gridDto.gridOptions.treeOptionDto?.autoExpandAll && {
|
||||
expandedRowKeys: expandedRowKeys,
|
||||
onRowExpanding: (e: any) => {
|
||||
setExpandedRowKeys((prev) => [...prev, e.key])
|
||||
},
|
||||
onRowCollapsing: (e: any) => {
|
||||
setExpandedRowKeys((prev) => prev.filter((k) => k !== e.key))
|
||||
},
|
||||
})}
|
||||
autoExpandAll={gridDto.gridOptions.treeOptionDto?.autoExpandAll || false}
|
||||
allowColumnResizing={gridDto.gridOptions.columnOptionDto?.allowColumnResizing}
|
||||
allowColumnReordering={gridDto.gridOptions.columnOptionDto?.allowColumnReordering}
|
||||
showBorders={gridDto.gridOptions.columnOptionDto?.showBorders}
|
||||
showRowLines={gridDto.gridOptions.columnOptionDto?.showRowLines}
|
||||
showColumnLines={gridDto.gridOptions.columnOptionDto?.showColumnLines}
|
||||
columnResizingMode={gridDto.gridOptions.columnOptionDto?.columnResizingMode}
|
||||
columnAutoWidth={gridDto.gridOptions.columnOptionDto?.columnAutoWidth}
|
||||
rtlEnabled={gridDto.gridOptions.columnOptionDto?.rtlEnabled}
|
||||
rowAlternationEnabled={gridDto.gridOptions.columnOptionDto?.rowAlternationEnabled}
|
||||
hoverStateEnabled={gridDto.gridOptions.columnOptionDto?.hoverStateEnabled}
|
||||
columnHidingEnabled={gridDto.gridOptions.columnOptionDto?.columnHidingEnabled}
|
||||
focusedRowEnabled={gridDto.gridOptions.columnOptionDto?.focusedRowEnabled}
|
||||
showColumnHeaders={gridDto.gridOptions.columnOptionDto?.showColumnHeaders}
|
||||
filterSyncEnabled={true}
|
||||
onSelectionChanged={onSelectionChanged}
|
||||
onInitNewRow={onInitNewRow}
|
||||
onCellPrepared={onCellPrepared}
|
||||
onRowInserting={onRowInserting}
|
||||
onRowUpdating={onRowUpdating}
|
||||
onEditingStart={onEditingStart}
|
||||
onDataErrorOccurred={onDataErrorOccurred}
|
||||
onEditCanceled={() => {
|
||||
setMode('view')
|
||||
setIsPopupFullScreen(false)
|
||||
}}
|
||||
onSaved={() => {
|
||||
setMode('view')
|
||||
setIsPopupFullScreen(false)
|
||||
}}
|
||||
onRowInserted={() => {
|
||||
props.refreshData?.()
|
||||
}}
|
||||
onRowUpdated={() => {
|
||||
props.refreshData?.()
|
||||
}}
|
||||
onRowRemoved={() => {
|
||||
props.refreshData?.()
|
||||
}}
|
||||
onContentReady={(e) => {
|
||||
// Restore expanded keys after data refresh (only if autoExpandAll is false)
|
||||
if (
|
||||
!gridDto.gridOptions.treeOptionDto?.autoExpandAll &&
|
||||
expandedRowKeys.length > 0
|
||||
) {
|
||||
e.component.option('expandedRowKeys', expandedRowKeys)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<RemoteOperations filtering={true} sorting={true} grouping={false} />
|
||||
<Editing
|
||||
refreshMode={gridDto.gridOptions.editingOptionDto?.refreshMode}
|
||||
mode={smaller.md ? 'form' : gridDto.gridOptions.editingOptionDto?.mode}
|
||||
allowDeleting={gridDto.gridOptions.editingOptionDto?.allowDeleting}
|
||||
allowUpdating={gridDto.gridOptions.editingOptionDto?.allowUpdating}
|
||||
allowAdding={gridDto.gridOptions.editingOptionDto?.allowAdding}
|
||||
useIcons={gridDto.gridOptions.editingOptionDto?.useIcons}
|
||||
popup={{
|
||||
title:
|
||||
(mode === 'new' ? '✚ ' : '🖊️ ') +
|
||||
translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title),
|
||||
showTitle: gridDto.gridOptions.editingOptionDto?.popup?.showTitle,
|
||||
hideOnOutsideClick:
|
||||
gridDto.gridOptions.editingOptionDto?.popup?.hideOnOutsideClick,
|
||||
width: gridDto.gridOptions.editingOptionDto?.popup?.width,
|
||||
height: gridDto.gridOptions.editingOptionDto?.popup?.height,
|
||||
resizeEnabled: gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled,
|
||||
fullScreen: isPopupFullScreen,
|
||||
toolbarItems: [
|
||||
{
|
||||
widget: 'dxButton',
|
||||
toolbar: 'top',
|
||||
location: 'after',
|
||||
options: {
|
||||
icon: isPopupFullScreen ? 'collapse' : 'fullscreen',
|
||||
hint: isPopupFullScreen
|
||||
? translate('::Normal Boyut')
|
||||
: translate('::Tam Ekran'),
|
||||
stylingMode: 'text',
|
||||
onClick: () => setIsPopupFullScreen(!isPopupFullScreen),
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
<Template name={'cellEditTagBox'} render={TagBoxEditorComponent} />
|
||||
<Template name={'cellEditGridBox'} render={GridBoxEditorComponent} />
|
||||
<Template name="extraFilters">
|
||||
<GridExtraFilterToolbar
|
||||
filters={gridDto?.gridOptions.extraFilterDto ?? []}
|
||||
extraFilters={extraFilters}
|
||||
setExtraFilters={setExtraFilters}
|
||||
/>
|
||||
</Template>
|
||||
<Toolbar
|
||||
visible={(toolbarData?.length ?? 0) > 0 || (filterToolbarData?.length ?? 0) > 0}
|
||||
>
|
||||
{toolbarData?.map((item) => (
|
||||
<Item key={item.name} {...item} />
|
||||
))}
|
||||
{filterToolbarData?.map((item) => (
|
||||
<Item key={item.name} {...item} />
|
||||
))}
|
||||
{gridDto?.gridOptions.extraFilterDto?.length ? (
|
||||
<Item location="before" template="extraFilters" cssClass="no-default" />
|
||||
) : null}
|
||||
</Toolbar>
|
||||
<Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
|
||||
<FilterRow
|
||||
visible={gridDto.gridOptions.filterRowDto?.visible}
|
||||
applyFilter={gridDto.gridOptions.filterRowDto?.applyFilter}
|
||||
></FilterRow>
|
||||
<FilterPanel visible={gridDto.gridOptions.filterPanelDto.visible}></FilterPanel>
|
||||
<HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
|
||||
<SearchPanel
|
||||
visible={gridDto.gridOptions.searchPanelDto.visible}
|
||||
width={gridDto.gridOptions.searchPanelDto.width}
|
||||
></SearchPanel>
|
||||
<Selection
|
||||
mode={gridDto.gridOptions.selectionDto?.mode}
|
||||
recursive={gridDto.gridOptions.treeOptionDto?.recursiveSelection || false}
|
||||
></Selection>
|
||||
<Pager
|
||||
visible={gridDto.gridOptions.pagerOptionDto?.visible}
|
||||
allowedPageSizes={gridDto.gridOptions.pagerOptionDto?.allowedPageSizes
|
||||
?.split(',')
|
||||
.map((a: any) => +a)}
|
||||
showPageSizeSelector={gridDto.gridOptions.pagerOptionDto?.showPageSizeSelector}
|
||||
showInfo={gridDto.gridOptions.pagerOptionDto?.showInfo}
|
||||
showNavigationButtons={gridDto.gridOptions.pagerOptionDto?.showNavigationButtons}
|
||||
infoText={gridDto.gridOptions.pagerOptionDto?.infoText}
|
||||
displayMode={gridDto.gridOptions.pagerOptionDto?.displayMode}
|
||||
></Pager>
|
||||
<ColumnChooser
|
||||
enabled={gridDto.gridOptions.columnOptionDto?.columnChooserEnabled}
|
||||
mode={gridDto.gridOptions.columnOptionDto?.columnChooserMode}
|
||||
></ColumnChooser>
|
||||
<ColumnFixing
|
||||
enabled={gridDto.gridOptions.columnOptionDto?.columnFixingEnabled}
|
||||
></ColumnFixing>
|
||||
<Scrolling mode={gridDto.gridOptions.pagerOptionDto?.scrollingMode}></Scrolling>
|
||||
<LoadPanel
|
||||
enabled={gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled}
|
||||
text={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
|
||||
></LoadPanel>
|
||||
</TreeListDx>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Dialog
|
||||
isOpen={toolbarModalData?.open || false}
|
||||
onClose={() => setToolbarModalData(undefined)}
|
||||
onRequestClose={() => setToolbarModalData(undefined)}
|
||||
>
|
||||
{toolbarModalData?.content}
|
||||
</Dialog>
|
||||
<GridFilterDialogs gridRef={gridRef as any} listFormCode={listFormCode} {...filterData} />
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tree
|
||||
|
|
@ -97,11 +97,18 @@ export function pivotFieldConvertDataType(fieldDbType?: DataType): PivotGridData
|
|||
}
|
||||
|
||||
export function setGridPanelColor(color: any) {
|
||||
const pnl = document.getElementsByClassName(
|
||||
const pnl1 = document.getElementsByClassName(
|
||||
'dx-datagrid-header-panel',
|
||||
) as HTMLCollectionOf<HTMLElement>
|
||||
if (pnl?.length) {
|
||||
pnl[0].style.backgroundColor = color
|
||||
if (pnl1?.length) {
|
||||
pnl1[0].style.backgroundColor = color
|
||||
}
|
||||
|
||||
const pnl2 = document.getElementsByClassName(
|
||||
'dx-treelist-header-panel',
|
||||
) as HTMLCollectionOf<HTMLElement>
|
||||
if (pnl2?.length) {
|
||||
pnl2[0].style.backgroundColor = color
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ import { getListFormCustomization } from '@/services/list-form-customization.ser
|
|||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import DataGrid from 'devextreme-react/data-grid'
|
||||
import PivotGrid from 'devextreme-react/pivot-grid'
|
||||
import TreeList from 'devextreme-react/tree-list'
|
||||
import { ToolbarItem } from 'devextreme/ui/data_grid_types'
|
||||
import dxDataGrid from 'devextreme/ui/data_grid'
|
||||
import dxPivotGrid from 'devextreme/ui/pivot_grid'
|
||||
import dxTreeList from 'devextreme/ui/tree_list'
|
||||
import { Dispatch, MutableRefObject, SetStateAction, useEffect, useState } from 'react'
|
||||
import { setGridPanelColor } from './Utils'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
|
|
@ -22,20 +24,29 @@ export interface ISelectBoxData {
|
|||
label?: string
|
||||
}
|
||||
|
||||
type GridInstance = dxDataGrid | dxPivotGrid | dxTreeList
|
||||
|
||||
// Grid tipini kontrol eden yardımcı fonksiyonlar
|
||||
const isDataGrid = (grid: dxDataGrid | dxPivotGrid): grid is dxDataGrid => {
|
||||
const isDataGrid = (grid: GridInstance): grid is dxDataGrid => {
|
||||
return 'clearFilter' in grid
|
||||
}
|
||||
|
||||
const getToolbarItems = (grid: dxDataGrid | dxPivotGrid): any[] => {
|
||||
const isTreeList = (grid: GridInstance): grid is dxTreeList => {
|
||||
return 'getRootNode' in grid
|
||||
}
|
||||
|
||||
const getToolbarItems = (grid: GridInstance): any[] => {
|
||||
if (isDataGrid(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
return toolbarOptions?.items || []
|
||||
} else if (isTreeList(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
return toolbarOptions?.items || []
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const setToolbarItemValue = (grid: dxDataGrid | dxPivotGrid, itemName: string, value: any) => {
|
||||
const setToolbarItemValue = (grid: GridInstance, itemName: string, value: any) => {
|
||||
if (isDataGrid(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
if (toolbarOptions?.items) {
|
||||
|
|
@ -48,10 +59,22 @@ const setToolbarItemValue = (grid: dxDataGrid | dxPivotGrid, itemName: string, v
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (isTreeList(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
if (toolbarOptions?.items) {
|
||||
const index = toolbarOptions.items.findIndex((item: any) => item.name === itemName)
|
||||
if (index > -1 && toolbarOptions.items[index]) {
|
||||
const item = toolbarOptions.items[index] as any
|
||||
if (item.options) {
|
||||
item.options.value = value
|
||||
grid.option('toolbar', toolbarOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const setToolbarItemItems = (grid: dxDataGrid | dxPivotGrid, itemName: string, items: any[]) => {
|
||||
const setToolbarItemItems = (grid: GridInstance, itemName: string, items: any[]) => {
|
||||
if (isDataGrid(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
if (toolbarOptions?.items) {
|
||||
|
|
@ -64,30 +87,50 @@ const setToolbarItemItems = (grid: dxDataGrid | dxPivotGrid, itemName: string, i
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (isTreeList(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
if (toolbarOptions?.items) {
|
||||
const index = toolbarOptions.items.findIndex((item: any) => item.name === itemName)
|
||||
if (index > -1 && toolbarOptions.items[index]) {
|
||||
const item = toolbarOptions.items[index] as any
|
||||
if (item.options) {
|
||||
item.options.items = items
|
||||
grid.option('toolbar', toolbarOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const clearGridFilter = (grid: dxDataGrid | dxPivotGrid) => {
|
||||
const clearGridFilter = (grid: GridInstance) => {
|
||||
if (isDataGrid(grid)) {
|
||||
grid.clearFilter()
|
||||
} else if (isTreeList(grid)) {
|
||||
grid.clearFilter()
|
||||
}
|
||||
}
|
||||
|
||||
const setFilterPanelVisible = (grid: dxDataGrid | dxPivotGrid, visible: boolean) => {
|
||||
const setFilterPanelVisible = (grid: GridInstance, visible: boolean) => {
|
||||
if (isDataGrid(grid)) {
|
||||
grid.option('filterPanel', { visible })
|
||||
} else if (isTreeList(grid)) {
|
||||
grid.option('filterPanel', { visible })
|
||||
}
|
||||
}
|
||||
|
||||
const setFilterValue = (grid: dxDataGrid | dxPivotGrid, value: any) => {
|
||||
const setFilterValue = (grid: GridInstance, value: any) => {
|
||||
if (isDataGrid(grid)) {
|
||||
grid.option('filterValue', value)
|
||||
} else if (isTreeList(grid)) {
|
||||
grid.option('filterValue', value)
|
||||
}
|
||||
}
|
||||
|
||||
const resetGridState = (grid: dxDataGrid | dxPivotGrid) => {
|
||||
const resetGridState = (grid: GridInstance) => {
|
||||
if (isDataGrid(grid)) {
|
||||
grid.state(null)
|
||||
} else if (isTreeList(grid)) {
|
||||
grid.state(null)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +143,7 @@ const useFilters = ({
|
|||
gridRef:
|
||||
| MutableRefObject<DataGrid<any, any> | undefined>
|
||||
| MutableRefObject<PivotGrid | undefined>
|
||||
| MutableRefObject<TreeList<any, any> | undefined>
|
||||
listFormCode: string
|
||||
}): {
|
||||
filterToolbarData: ToolbarItem[]
|
||||
|
|
|
|||
Loading…
Reference in a new issue