Wizard Edit özelliği eklendi
This commit is contained in:
parent
ea3e847490
commit
b2dfb04879
16 changed files with 572 additions and 216 deletions
|
|
@ -7,6 +7,7 @@ public interface IListFormWizardAppService
|
|||
{
|
||||
Task Create(ListFormWizardDto input);
|
||||
Task<List<WizardFileInfoDto>> GetFiles();
|
||||
Task<WizardSeedFileDto> GetFile(string fileName);
|
||||
Task DeleteFile(string fileName);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -398,6 +398,24 @@ public class ListFormWizardAppService(
|
|||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public async Task<WizardSeedFileDto> GetFile(string fileName)
|
||||
{
|
||||
// Güvenlik: sadece dosya adı, path traversal yasak
|
||||
if (fileName.Contains('/') || fileName.Contains('\\') || fileName.Contains(".."))
|
||||
throw new Volo.Abp.AbpException("Geçersiz dosya adı.");
|
||||
|
||||
var outputPath = ResolveWizardSeedOutputPath();
|
||||
var filePath = Path.Combine(outputPath, fileName);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
throw new Volo.Abp.AbpException($"Dosya bulunamadı: {fileName}");
|
||||
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
var seed = JsonSerializer.Deserialize<WizardSeedFileDto>(json, options);
|
||||
return seed ?? throw new Volo.Abp.AbpException("Dosya okunamadı.");
|
||||
}
|
||||
|
||||
public async Task DeleteFile(string fileName)
|
||||
{
|
||||
// Güvenlik: sadece dosya adı, path traversal yasak
|
||||
|
|
|
|||
|
|
@ -16040,6 +16040,12 @@
|
|||
"en": "Menu Information",
|
||||
"tr": "Menü Bilgileri"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.Wizard.AddNewRecord",
|
||||
"en": "Add New Wizard",
|
||||
"tr": "Yeni Sihirbaz Ekle"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.Wizard.Required",
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
"EditorScript": "",
|
||||
"ColSpan": 1,
|
||||
"IsRequired": true,
|
||||
"DbSourceType": 9,
|
||||
"DbSourceType": 12,
|
||||
"TurkishCaption": "Id",
|
||||
"EnglishCaption": "Id",
|
||||
"LookupDataSourceType": 1,
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
"EditorScript": "",
|
||||
"ColSpan": 1,
|
||||
"IsRequired": false,
|
||||
"DbSourceType": 9,
|
||||
"DbSourceType": 12,
|
||||
"TurkishCaption": "Branch Id",
|
||||
"EnglishCaption": "Branch Id",
|
||||
"LookupDataSourceType": 2,
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
"EditorScript": "",
|
||||
"ColSpan": 1,
|
||||
"IsRequired": true,
|
||||
"DbSourceType": 16,
|
||||
"DbSourceType": 12,
|
||||
"TurkishCaption": "Name",
|
||||
"EnglishCaption": "Name",
|
||||
"LookupDataSourceType": 1,
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
"EditorScript": "",
|
||||
"ColSpan": 1,
|
||||
"IsRequired": false,
|
||||
"DbSourceType": 9,
|
||||
"DbSourceType": 12,
|
||||
"TurkishCaption": "Parent Id",
|
||||
"EnglishCaption": "Parent Id",
|
||||
"LookupDataSourceType": 2,
|
||||
|
|
@ -1,4 +1,54 @@
|
|||
{
|
||||
"commit": "aac3f4a",
|
||||
"releases": []
|
||||
"commit": "ea3e847",
|
||||
"releases": [
|
||||
{
|
||||
"version": "1.0.5",
|
||||
"buildDate": "2026-04-28",
|
||||
"commit": "b9cc68ff41d675fefadab79f5ea2c5e7f376708a",
|
||||
"changeLog": [
|
||||
"- AllowAdding özelliği eklendi.",
|
||||
"- Kulllanıcı bazında Workhour özelliği eklendi.",
|
||||
"- ConcurrentUser sınırlaması getirildi.",
|
||||
"- Uygulamadan kullanıcıyı kickleme özelliği getirildi.",
|
||||
"- Uygulama açıkken DbMigrator çağrısı yapıldı."
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.4",
|
||||
"buildDate": "2026-03-30",
|
||||
"commit": "e9ce256c0706de408e08a462bee9e4a72653f2c7",
|
||||
"changeLog": [
|
||||
"- Role Yetkilerini kopyalama",
|
||||
"- Place Holder güncellemesi",
|
||||
"- Kayıt kopyalama özelliği"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.3",
|
||||
"buildDate": "2026-03-28",
|
||||
"commit": "130d35c37703935e34948419f2ee900cc1b6b28c",
|
||||
"changeLog": [
|
||||
"Report Template View And Design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.2",
|
||||
"buildDate": "2026-03-21",
|
||||
"commit": "196b0dc24b7a815586166679b58ab4f9334bd40e",
|
||||
"changeLog": [
|
||||
"Artificial Intelligence Chat Bot güncellemeleri"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.1",
|
||||
"buildDate": "2026-03-18",
|
||||
"commit": "ac7784c030825158641e9042c50dede2067c0486",
|
||||
"changeLog": [
|
||||
"Public Site Designer",
|
||||
"Menu Groups",
|
||||
"Sql Query Manager",
|
||||
"Listform Wizard"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import {
|
|||
EditingFormDto,
|
||||
ExtraFilterEditDto,
|
||||
FieldsDefaultValueDto,
|
||||
SelectCommandTypeEnum,
|
||||
SubFormDto,
|
||||
WidgetEditDto,
|
||||
} from '../../form/models'
|
||||
|
|
@ -15,71 +14,6 @@ import {
|
|||
ChartValueAxisDto,
|
||||
} from '../charts/models'
|
||||
|
||||
export interface ListFormWizardColumnItemDto {
|
||||
dataField: string
|
||||
editorType: string
|
||||
editorOptions: string
|
||||
editorScript: string
|
||||
colSpan: number
|
||||
isRequired: boolean
|
||||
dbSourceType: number
|
||||
}
|
||||
|
||||
export interface ListFormWizardColumnGroupDto {
|
||||
caption: string
|
||||
colCount: number
|
||||
items: ListFormWizardColumnItemDto[]
|
||||
}
|
||||
|
||||
export interface ListFormWizardDto {
|
||||
wizardName: string
|
||||
listFormCode: string
|
||||
menuCode: string
|
||||
isTenant: boolean
|
||||
isBranch: boolean
|
||||
isOrganizationUnit: boolean
|
||||
allowAdding: boolean
|
||||
allowUpdating: boolean
|
||||
allowDeleting: boolean
|
||||
confirmDelete: boolean
|
||||
allowDetail: boolean
|
||||
|
||||
defaultLayout: ListViewLayoutType
|
||||
grid: boolean
|
||||
pivot: boolean
|
||||
tree: boolean
|
||||
chart: boolean
|
||||
gantt: boolean
|
||||
scheduler: boolean
|
||||
|
||||
languageTextMenuEn: string
|
||||
languageTextMenuTr: string
|
||||
languageTextTitleEn: string
|
||||
languageTextTitleTr: string
|
||||
languageTextDescEn: string
|
||||
languageTextDescTr: string
|
||||
languageTextMenuParentEn: string
|
||||
languageTextMenuParentTr: string
|
||||
permissionGroupName: string
|
||||
menuParentCode: string
|
||||
menuIcon: string
|
||||
dataSourceCode: string
|
||||
dataSourceConnectionString: string
|
||||
selectCommandType: SelectCommandTypeEnum
|
||||
selectCommand: string
|
||||
keyFieldName: string
|
||||
keyFieldDbSourceType: number
|
||||
groups?: ListFormWizardColumnGroupDto[]
|
||||
}
|
||||
|
||||
export interface WizardFileInfoDto {
|
||||
fileName: string
|
||||
wizardName: string
|
||||
listFormCode: string
|
||||
createdAt: string
|
||||
hasInsertedRecords: boolean
|
||||
}
|
||||
|
||||
export interface ListFormJsonRowDto {
|
||||
id?: string
|
||||
index: number
|
||||
|
|
|
|||
109
ui/src/proxy/admin/wizard/models.ts
Normal file
109
ui/src/proxy/admin/wizard/models.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { SelectCommandTypeEnum } from "@/proxy/form/models"
|
||||
import { ListViewLayoutType } from "@/views/admin/listForm/edit/types"
|
||||
|
||||
export interface ListFormWizardColumnItemDto {
|
||||
dataField: string
|
||||
editorType: string
|
||||
editorOptions: string
|
||||
editorScript: string
|
||||
colSpan: number
|
||||
isRequired: boolean
|
||||
dbSourceType: number
|
||||
}
|
||||
|
||||
export interface ListFormWizardColumnGroupDto {
|
||||
caption: string
|
||||
colCount: number
|
||||
items: ListFormWizardColumnItemDto[]
|
||||
}
|
||||
|
||||
export interface ListFormWizardDto {
|
||||
wizardName: string
|
||||
listFormCode: string
|
||||
menuCode: string
|
||||
isTenant: boolean
|
||||
isBranch: boolean
|
||||
isOrganizationUnit: boolean
|
||||
allowAdding: boolean
|
||||
allowUpdating: boolean
|
||||
allowDeleting: boolean
|
||||
confirmDelete: boolean
|
||||
allowDetail: boolean
|
||||
|
||||
defaultLayout: ListViewLayoutType
|
||||
grid: boolean
|
||||
pivot: boolean
|
||||
tree: boolean
|
||||
chart: boolean
|
||||
gantt: boolean
|
||||
scheduler: boolean
|
||||
|
||||
languageTextMenuEn: string
|
||||
languageTextMenuTr: string
|
||||
languageTextTitleEn: string
|
||||
languageTextTitleTr: string
|
||||
languageTextDescEn: string
|
||||
languageTextDescTr: string
|
||||
languageTextMenuParentEn: string
|
||||
languageTextMenuParentTr: string
|
||||
permissionGroupName: string
|
||||
menuParentCode: string
|
||||
menuIcon: string
|
||||
dataSourceCode: string
|
||||
dataSourceConnectionString: string
|
||||
selectCommandType: SelectCommandTypeEnum
|
||||
selectCommand: string
|
||||
keyFieldName: string
|
||||
keyFieldDbSourceType: number
|
||||
groups?: ListFormWizardColumnGroupDto[]
|
||||
}
|
||||
|
||||
export interface WizardFileInfoDto {
|
||||
fileName: string
|
||||
wizardName: string
|
||||
listFormCode: string
|
||||
createdAt: string
|
||||
hasInsertedRecords: boolean
|
||||
}
|
||||
|
||||
export interface WizardInsertedRecordsDto {
|
||||
languageKeys: string[]
|
||||
permissionGroupNames: string[]
|
||||
permissionNames: string[]
|
||||
menuCodes: string[]
|
||||
dataSourceCodes: string[]
|
||||
}
|
||||
|
||||
export interface WizardSeedFileItemDto {
|
||||
dataField: string
|
||||
editorType: string
|
||||
editorOptions: string
|
||||
editorScript: string
|
||||
colSpan: number
|
||||
isRequired: boolean
|
||||
dbSourceType: number
|
||||
turkishCaption?: string
|
||||
englishCaption?: string
|
||||
captionName?: string
|
||||
lookupDataSourceType?: number
|
||||
valueExpr?: string
|
||||
displayExpr?: string
|
||||
lookupQuery?: string
|
||||
}
|
||||
|
||||
export interface WizardSeedFileGroupDto {
|
||||
caption: string
|
||||
colCount: number
|
||||
items: WizardSeedFileItemDto[]
|
||||
}
|
||||
|
||||
export interface WizardSeedFileWizardDto extends Omit<ListFormWizardDto, 'groups'> {
|
||||
groups?: WizardSeedFileGroupDto[]
|
||||
}
|
||||
|
||||
export interface WizardSeedFileDto {
|
||||
wizard: WizardSeedFileWizardDto
|
||||
isDeletedField: boolean
|
||||
isCreatedField: boolean
|
||||
insertedRecords: WizardInsertedRecordsDto
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { ListFormWizardDto, WizardFileInfoDto } from '../proxy/admin/list-form/models'
|
||||
import { ListFormWizardDto, WizardFileInfoDto, WizardSeedFileDto } from '@/proxy/admin/wizard/models'
|
||||
import apiService from './api.service'
|
||||
|
||||
export const postListFormWizard = (input: ListFormWizardDto) =>
|
||||
|
|
@ -14,6 +14,13 @@ export const getWizardFiles = () =>
|
|||
url: `/api/app/list-form-wizard/files`,
|
||||
})
|
||||
|
||||
export const getWizardFile = (fileName: string) =>
|
||||
apiService.fetchData<WizardSeedFileDto>({
|
||||
method: 'GET',
|
||||
url: `/api/app/list-form-wizard/file`,
|
||||
params: { fileName },
|
||||
})
|
||||
|
||||
export const deleteWizardFile = (fileName: string) =>
|
||||
apiService.fetchData({
|
||||
method: 'DELETE',
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import { FormContainer, Notification, Steps, toast } from '@/components/ui'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/list-form/models'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { Form, Formik, FormikProps } from 'formik'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import * as Yup from 'yup'
|
||||
import { getMenus } from '@/services/menu.service'
|
||||
import { getPermissions } from '@/services/identity.service'
|
||||
|
|
@ -23,12 +22,14 @@ import WizardStep1, {
|
|||
findRootCode,
|
||||
} from './WizardStep1'
|
||||
import WizardStep2 from './WizardStep2'
|
||||
import WizardStep3, { WizardGroup } from './WizardStep3'
|
||||
import WizardStep3, { WizardGroup, WizardGroupItem } from './WizardStep3'
|
||||
import WizardStep4 from './WizardStep4'
|
||||
import { Container } from '@/components/shared'
|
||||
import { sqlDataTypeToDbType } from '../edit/options'
|
||||
import { useStoreActions } from '@/store/store'
|
||||
import { postListFormWizard } from '@/services/wizard.service'
|
||||
import { deleteWizardFile, getWizardFile, postListFormWizard } from '@/services/wizard.service'
|
||||
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/wizard/models'
|
||||
|
||||
// ─── Formik initial values & validation ──────────────────────────────────────
|
||||
const initialValues: ListFormWizardDto = {
|
||||
|
|
@ -106,6 +107,13 @@ const listFormValidationSchema = step1ValidationSchema.concat(step2ValidationSch
|
|||
const Wizard = () => {
|
||||
const [currentStep, setCurrentStep] = useState(0)
|
||||
|
||||
// ── Edit mode ──
|
||||
const location = useLocation()
|
||||
const editFileName: string | null = (location.state as any)?.editFileName ?? null
|
||||
const isEditMode = !!editFileName
|
||||
const [isLoadingEditData, setIsLoadingEditData] = useState(false)
|
||||
const editDataLoadedRef = useRef(false)
|
||||
|
||||
// ── Data Source ──
|
||||
const [isLoadingDataSource, setIsLoadingDataSource] = useState(false)
|
||||
const [dataSourceList, setDataSourceList] = useState<SelectBoxOption[]>([])
|
||||
|
|
@ -259,6 +267,118 @@ const Wizard = () => {
|
|||
getPermissionGroupList()
|
||||
}, [])
|
||||
|
||||
// ── Load edit data after reference lists are ready ──
|
||||
useEffect(() => {
|
||||
if (!isEditMode || !editFileName) return
|
||||
if (editDataLoadedRef.current) return
|
||||
if (isLoadingMenu || isLoadingDataSource || isLoadingPermissionGroup) return
|
||||
if (menuTree.length === 0 && dataSourceList.length === 0) return
|
||||
|
||||
editDataLoadedRef.current = true
|
||||
|
||||
const loadEditData = async () => {
|
||||
setIsLoadingEditData(true)
|
||||
try {
|
||||
const res = await getWizardFile(editFileName)
|
||||
const seed = res.data
|
||||
if (!seed?.wizard) return
|
||||
|
||||
const w = seed.wizard
|
||||
|
||||
// Populate formik values
|
||||
formikRef.current?.setValues({
|
||||
wizardName: w.wizardName ?? '',
|
||||
listFormCode: w.listFormCode ?? '',
|
||||
menuCode: w.menuCode ?? '',
|
||||
isTenant: w.isTenant ?? false,
|
||||
isBranch: w.isBranch ?? false,
|
||||
isOrganizationUnit: w.isOrganizationUnit ?? false,
|
||||
allowAdding: w.allowAdding ?? true,
|
||||
allowUpdating: w.allowUpdating ?? true,
|
||||
allowDeleting: w.allowDeleting ?? true,
|
||||
confirmDelete: w.confirmDelete ?? true,
|
||||
allowDetail: w.allowDetail ?? false,
|
||||
defaultLayout: w.defaultLayout ?? 'grid',
|
||||
grid: w.grid ?? true,
|
||||
pivot: w.pivot ?? true,
|
||||
tree: w.tree ?? true,
|
||||
chart: w.chart ?? true,
|
||||
gantt: w.gantt ?? true,
|
||||
scheduler: w.scheduler ?? true,
|
||||
languageTextMenuEn: w.languageTextMenuEn ?? '',
|
||||
languageTextMenuTr: w.languageTextMenuTr ?? '',
|
||||
languageTextTitleEn: w.languageTextTitleEn ?? '',
|
||||
languageTextTitleTr: w.languageTextTitleTr ?? '',
|
||||
languageTextDescEn: w.languageTextDescEn ?? '',
|
||||
languageTextDescTr: w.languageTextDescTr ?? '',
|
||||
languageTextMenuParentEn: w.languageTextMenuParentEn ?? '',
|
||||
languageTextMenuParentTr: w.languageTextMenuParentTr ?? '',
|
||||
permissionGroupName: w.permissionGroupName ?? '',
|
||||
menuParentCode: w.menuParentCode ?? '',
|
||||
menuIcon: w.menuIcon ?? '',
|
||||
dataSourceCode: w.dataSourceCode ?? '',
|
||||
dataSourceConnectionString: w.dataSourceConnectionString ?? '',
|
||||
selectCommandType: w.selectCommandType ?? SelectCommandTypeEnum.Table,
|
||||
selectCommand: w.selectCommand ?? '',
|
||||
keyFieldName: w.keyFieldName ?? '',
|
||||
keyFieldDbSourceType: w.keyFieldDbSourceType ?? DbTypeEnum.Int32,
|
||||
})
|
||||
|
||||
// Restore datasource to trigger db objects load
|
||||
if (w.dataSourceCode) {
|
||||
setCurrentDataSource(w.dataSourceCode)
|
||||
}
|
||||
|
||||
// Restore groups → WizardGroup[]
|
||||
if (w.groups && w.groups.length > 0) {
|
||||
const restoredGroups: WizardGroup[] = w.groups.map((g: any, gi: number) => ({
|
||||
id: `grp_edit_${gi}_${Date.now()}`,
|
||||
caption: g.caption ?? '',
|
||||
colCount: g.colCount ?? 2,
|
||||
items: (g.items ?? []).map(
|
||||
(it: any, ii: number) =>
|
||||
({
|
||||
id: `${it.dataField}_edit_${ii}_${Date.now()}`,
|
||||
dataField: it.dataField ?? '',
|
||||
editorType: it.editorType ?? 'dxTextBox',
|
||||
editorOptions: it.editorOptions ?? '',
|
||||
editorScript: it.editorScript ?? '',
|
||||
colSpan: it.colSpan ?? 1,
|
||||
isRequired: it.isRequired ?? false,
|
||||
turkishCaption: it.turkishCaption ?? it.dataField,
|
||||
englishCaption: it.englishCaption ?? it.dataField,
|
||||
captionName: it.captionName ?? `App.Listform.ListformField.${it.dataField}`,
|
||||
lookupDataSourceType:
|
||||
(it.lookupDataSourceType as UiLookupDataSourceTypeEnum) ??
|
||||
UiLookupDataSourceTypeEnum.StaticData,
|
||||
valueExpr: it.valueExpr ?? 'Key',
|
||||
displayExpr: it.displayExpr ?? 'Name',
|
||||
lookupQuery: it.lookupQuery ?? '',
|
||||
}) as WizardGroupItem,
|
||||
),
|
||||
}))
|
||||
setEditingGroups(restoredGroups)
|
||||
|
||||
// Restore selectedColumns from all group items
|
||||
const allFields = new Set(restoredGroups.flatMap((g) => g.items.map((i) => i.dataField)))
|
||||
setSelectedColumns(allFields)
|
||||
}
|
||||
} catch {
|
||||
toast.push(
|
||||
<Notification type="danger">
|
||||
{translate('::App.Listforms.WizardFileLoadError') || 'Failed to load wizard file.'}
|
||||
</Notification>,
|
||||
{ placement: 'top-end' },
|
||||
)
|
||||
} finally {
|
||||
setIsLoadingEditData(false)
|
||||
}
|
||||
}
|
||||
|
||||
loadEditData()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [editFileName, isLoadingMenu, isLoadingDataSource, isLoadingPermissionGroup])
|
||||
|
||||
const navigate = useNavigate()
|
||||
const formikRef = useRef<FormikProps<ListFormWizardDto>>(null)
|
||||
|
||||
|
|
@ -365,6 +485,11 @@ const Wizard = () => {
|
|||
|
||||
const values = formikRef.current.values
|
||||
|
||||
// Edit modunda: önce eski dosyayı sil (DB kayıtlarını temizler)
|
||||
if (isEditMode && editFileName) {
|
||||
await deleteWizardFile(editFileName)
|
||||
}
|
||||
|
||||
// 🔴 Önce kayıt işlemi TAMAMLANSIN
|
||||
await postListFormWizard({
|
||||
...values,
|
||||
|
|
@ -418,7 +543,7 @@ const Wizard = () => {
|
|||
<Container>
|
||||
<Helmet
|
||||
titleTemplate={`%s | ${APP_NAME}`}
|
||||
title={translate('::' + 'App.Listforms.Wizard')}
|
||||
title={translate('::' + (isEditMode ? 'App.Listforms.WizardEdit' : 'App.Listforms.Wizard'))}
|
||||
defaultTitle={APP_NAME}
|
||||
/>
|
||||
|
||||
|
|
@ -435,130 +560,138 @@ const Wizard = () => {
|
|||
</Steps>
|
||||
</div>
|
||||
|
||||
{isLoadingEditData && (
|
||||
<p className="text-xs text-gray-400 text-center py-4 animate-pulse">
|
||||
{translate('::App.Platform.Loading') || 'Loading...'}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<Formik
|
||||
innerRef={formikRef}
|
||||
initialValues={{ ...initialValues }}
|
||||
validationSchema={listFormValidationSchema}
|
||||
onSubmit={async (values, { setSubmitting }) => {
|
||||
setSubmitting(true)
|
||||
onSubmit={async (values, { setSubmitting }) => {
|
||||
setSubmitting(true)
|
||||
|
||||
try {
|
||||
// 🔴 1. Kaydet (bekle)
|
||||
await postListFormWizard({ ...values })
|
||||
try {
|
||||
// 🔴 1. Kaydet (bekle)
|
||||
await postListFormWizard({ ...values })
|
||||
|
||||
// 🔴 2. Config güncelle (bekle)
|
||||
await getConfig(true)
|
||||
// 🔴 2. Config güncelle (bekle)
|
||||
await getConfig(true)
|
||||
|
||||
// 🔴 3. Navigate
|
||||
navigate(
|
||||
ROUTES_ENUM.protected.admin.list.replace(':listFormCode', values.listFormCode),
|
||||
{ replace: true },
|
||||
)
|
||||
// 🔴 3. Navigate
|
||||
navigate(
|
||||
ROUTES_ENUM.protected.admin.list.replace(':listFormCode', values.listFormCode),
|
||||
{ replace: true },
|
||||
)
|
||||
|
||||
// 🔴 4. Toast (istersen navigate öncesi de olabilir)
|
||||
toast.push(
|
||||
<Notification type="success" duration={2000}>
|
||||
{translate('::ListForms.FormBilgileriKaydedildi')}
|
||||
</Notification>,
|
||||
{ placement: 'top-end' },
|
||||
)
|
||||
} catch (error: any) {
|
||||
toast.push(<Notification title={error.message} type="danger" />, {
|
||||
placement: 'top-end',
|
||||
})
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer
|
||||
size={currentStep === 2 ? undefined : currentStep === 3 ? undefined : 'sm'}
|
||||
>
|
||||
{/* ─── Step 1: Basic Info ─────────────────────────────── */}
|
||||
{currentStep === 0 && (
|
||||
<WizardStep1
|
||||
values={values}
|
||||
errors={errors}
|
||||
touched={touched}
|
||||
wizardName={values.wizardName}
|
||||
onWizardNameChange={handleWizardNameChange}
|
||||
rawMenuItems={rawMenuItems}
|
||||
menuTree={menuTree}
|
||||
isLoadingMenu={isLoadingMenu}
|
||||
onMenuParentChange={handleMenuParentChange}
|
||||
onClearMenuParent={() => formikRef.current?.setFieldValue('menuParentCode', '')}
|
||||
onReloadMenu={getMenuList}
|
||||
permissionGroupList={permissionGroupList}
|
||||
isLoadingPermissionGroup={isLoadingPermissionGroup}
|
||||
onNext={handleNext}
|
||||
translate={translate}
|
||||
/>
|
||||
)}
|
||||
// 🔴 4. Toast (istersen navigate öncesi de olabilir)
|
||||
toast.push(
|
||||
<Notification type="success" duration={2000}>
|
||||
{translate('::ListForms.FormBilgileriKaydedildi')}
|
||||
</Notification>,
|
||||
{ placement: 'top-end' },
|
||||
)
|
||||
} catch (error: any) {
|
||||
toast.push(<Notification title={error.message} type="danger" />, {
|
||||
placement: 'top-end',
|
||||
})
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({ touched, errors, isSubmitting, values }) => (
|
||||
<Form>
|
||||
<FormContainer
|
||||
size={currentStep === 2 ? undefined : currentStep === 3 ? undefined : 'sm'}
|
||||
>
|
||||
{/* ─── Step 1: Basic Info ─────────────────────────────── */}
|
||||
{currentStep === 0 && (
|
||||
<WizardStep1
|
||||
values={values}
|
||||
errors={errors}
|
||||
touched={touched}
|
||||
wizardName={values.wizardName}
|
||||
onWizardNameChange={handleWizardNameChange}
|
||||
rawMenuItems={rawMenuItems}
|
||||
menuTree={menuTree}
|
||||
isLoadingMenu={isLoadingMenu}
|
||||
onMenuParentChange={handleMenuParentChange}
|
||||
onClearMenuParent={() =>
|
||||
formikRef.current?.setFieldValue('menuParentCode', '')
|
||||
}
|
||||
onReloadMenu={getMenuList}
|
||||
permissionGroupList={permissionGroupList}
|
||||
isLoadingPermissionGroup={isLoadingPermissionGroup}
|
||||
onNext={handleNext}
|
||||
translate={translate}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* ─── Step 2: Data Settings ───────────────────────────── */}
|
||||
{currentStep === 1 && (
|
||||
<WizardStep2
|
||||
values={values}
|
||||
errors={errors}
|
||||
touched={touched}
|
||||
isLoadingDataSource={isLoadingDataSource}
|
||||
dataSourceList={dataSourceList}
|
||||
isDataSourceNew={isDataSourceNew}
|
||||
onDataSourceSelect={setCurrentDataSource}
|
||||
onDataSourceNewChange={setIsDataSourceNew}
|
||||
dbObjects={dbObjects}
|
||||
isLoadingDbObjects={isLoadingDbObjects}
|
||||
selectCommandColumns={selectCommandColumns}
|
||||
isLoadingColumns={isLoadingColumns}
|
||||
selectedColumns={selectedColumns}
|
||||
onLoadColumns={loadColumns}
|
||||
onClearColumns={() => {
|
||||
setSelectCommandColumns([])
|
||||
setSelectedColumns(new Set())
|
||||
}}
|
||||
onToggleColumn={toggleColumn}
|
||||
onToggleAllColumns={toggleAllColumns}
|
||||
translate={translate}
|
||||
onBack={handleBack}
|
||||
onNext={handleNext2}
|
||||
/>
|
||||
)}
|
||||
{/* ─── Step 2: Data Settings ───────────────────────────── */}
|
||||
{currentStep === 1 && (
|
||||
<WizardStep2
|
||||
values={values}
|
||||
errors={errors}
|
||||
touched={touched}
|
||||
isLoadingDataSource={isLoadingDataSource}
|
||||
dataSourceList={dataSourceList}
|
||||
isDataSourceNew={isDataSourceNew}
|
||||
onDataSourceSelect={setCurrentDataSource}
|
||||
onDataSourceNewChange={setIsDataSourceNew}
|
||||
dbObjects={dbObjects}
|
||||
isLoadingDbObjects={isLoadingDbObjects}
|
||||
selectCommandColumns={selectCommandColumns}
|
||||
isLoadingColumns={isLoadingColumns}
|
||||
selectedColumns={selectedColumns}
|
||||
onLoadColumns={loadColumns}
|
||||
onClearColumns={() => {
|
||||
setSelectCommandColumns([])
|
||||
setSelectedColumns(new Set())
|
||||
}}
|
||||
onToggleColumn={toggleColumn}
|
||||
onToggleAllColumns={toggleAllColumns}
|
||||
translate={translate}
|
||||
onBack={handleBack}
|
||||
onNext={handleNext2}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* ─── Step 3: List Form Fields ───────────────────────────── */}
|
||||
{currentStep === 2 && (
|
||||
<WizardStep3
|
||||
selectedColumns={selectedColumns}
|
||||
selectCommandColumns={selectCommandColumns}
|
||||
groups={editingGroups}
|
||||
onGroupsChange={setEditingGroups}
|
||||
dbObjects={dbObjects}
|
||||
isLoadingDbObjects={isLoadingDbObjects}
|
||||
dsCode={currentDataSource}
|
||||
translate={translate}
|
||||
onBack={() => setCurrentStep(1)}
|
||||
onNext={() => setCurrentStep(3)}
|
||||
/>
|
||||
)}
|
||||
{/* ─── Step 3: List Form Fields ───────────────────────────── */}
|
||||
{currentStep === 2 && (
|
||||
<WizardStep3
|
||||
selectedColumns={selectedColumns}
|
||||
selectCommandColumns={selectCommandColumns}
|
||||
groups={editingGroups}
|
||||
onGroupsChange={setEditingGroups}
|
||||
dbObjects={dbObjects}
|
||||
isLoadingDbObjects={isLoadingDbObjects}
|
||||
dsCode={currentDataSource}
|
||||
translate={translate}
|
||||
onBack={() => setCurrentStep(1)}
|
||||
onNext={() => setCurrentStep(3)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* ─── Step 4: Deploy ───────────────────────────── */}
|
||||
{currentStep === 3 && (
|
||||
<WizardStep4
|
||||
values={values}
|
||||
wizardName={values.wizardName}
|
||||
selectedColumns={selectedColumns}
|
||||
selectCommandColumns={selectCommandColumns}
|
||||
groups={editingGroups}
|
||||
translate={translate}
|
||||
onBack={() => setCurrentStep(2)}
|
||||
onSubmit={handleDeploy}
|
||||
/>
|
||||
)}
|
||||
</FormContainer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
{/* ─── Step 4: Deploy ───────────────────────────── */}
|
||||
{currentStep === 3 && (
|
||||
<WizardStep4
|
||||
values={values}
|
||||
wizardName={values.wizardName}
|
||||
selectedColumns={selectedColumns}
|
||||
selectCommandColumns={selectCommandColumns}
|
||||
groups={editingGroups}
|
||||
translate={translate}
|
||||
onBack={() => setCurrentStep(2)}
|
||||
onSubmit={handleDeploy}
|
||||
/>
|
||||
)}
|
||||
</FormContainer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom'
|
|||
import classNames from 'classnames'
|
||||
import { Button, Input, Notification, toast } from '@/components/ui'
|
||||
import Container from '@/components/shared/Container'
|
||||
import { WizardFileInfoDto } from '@/proxy/admin/list-form/models'
|
||||
import ConfirmDialog from '@/components/shared/ConfirmDialog'
|
||||
import {
|
||||
FaTrash,
|
||||
FaSync,
|
||||
|
|
@ -11,12 +11,16 @@ import {
|
|||
FaPlus,
|
||||
FaExclamationTriangle,
|
||||
FaSearch,
|
||||
FaEdit,
|
||||
} from 'react-icons/fa'
|
||||
import { FcAcceptDatabase } from 'react-icons/fc'
|
||||
import { deleteWizardFile, getWizardFiles } from '@/services/wizard.service'
|
||||
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useStoreState } from '@/store/store'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { WizardFileInfoDto } from '@/proxy/admin/wizard/models'
|
||||
import { UiEvalService } from '@/services/UiEvalService'
|
||||
|
||||
// Timestamp formatı: "202605021730" → "2026-05-02 17:30"
|
||||
const formatTimestamp = (raw: string): string => {
|
||||
|
|
@ -45,6 +49,7 @@ const WizardFileManager = () => {
|
|||
const [deletingFile, setDeletingFile] = useState<string | null>(null)
|
||||
const [confirm, setConfirm] = useState<ConfirmState | null>(null)
|
||||
const [search, setSearch] = useState('')
|
||||
const [showDbMigrateDialog, setShowDbMigrateDialog] = useState(false)
|
||||
|
||||
const filteredFiles = useMemo(() => {
|
||||
const q = search.trim().toLowerCase()
|
||||
|
|
@ -123,7 +128,7 @@ const WizardFileManager = () => {
|
|||
<div className="relative">
|
||||
<FaSearch className="absolute left-2 top-1/2 -translate-y-1/2 text-gray-400 text-xs pointer-events-none" />
|
||||
<Input
|
||||
size="sm"
|
||||
size="xs"
|
||||
className="pl-6 w-44"
|
||||
placeholder={translate('::App.Platform.Search') || 'Search...'}
|
||||
value={search}
|
||||
|
|
@ -131,7 +136,7 @@ const WizardFileManager = () => {
|
|||
/>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
size="xs"
|
||||
variant="default"
|
||||
title={translate('::App.Platform.Refresh') || 'Yenile'}
|
||||
loading={loading}
|
||||
|
|
@ -140,13 +145,22 @@ const WizardFileManager = () => {
|
|||
<FaSync />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
size="xs"
|
||||
variant="default"
|
||||
icon={<FcAcceptDatabase />}
|
||||
onClick={() => setShowDbMigrateDialog(true)}
|
||||
title={translate('::App.DbMigrate.StartMessage') || 'Run DB Migration'}
|
||||
>
|
||||
{translate('::ListForms.ListForm.DbMigrate') || 'DB Migrate'}
|
||||
</Button>
|
||||
<Button
|
||||
size="xs"
|
||||
variant="solid"
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.saas.listFormManagement.wizard)}
|
||||
className="flex items-center"
|
||||
>
|
||||
<FaPlus className="mr-1" />
|
||||
{translate('::ListForms.ListForm.AddNewRecord') || 'Add New Record'}
|
||||
{translate('::ListForms.Wizard.AddNewRecord') || 'Add New Record'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -192,6 +206,20 @@ const WizardFileManager = () => {
|
|||
<FaExclamationTriangle />
|
||||
</span>
|
||||
)}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="plain"
|
||||
className="text-indigo-500 hover:bg-indigo-50 dark:hover:bg-indigo-900/20"
|
||||
type="button"
|
||||
title={translate('::App.Platform.Edit') || 'Edit'}
|
||||
onClick={() =>
|
||||
navigate(ROUTES_ENUM.protected.saas.listFormManagement.wizard, {
|
||||
state: { editFileName: f.fileName },
|
||||
})
|
||||
}
|
||||
>
|
||||
<FaEdit />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="plain"
|
||||
|
|
@ -209,8 +237,30 @@ const WizardFileManager = () => {
|
|||
))}
|
||||
</div>
|
||||
|
||||
{/* Confirm Dialog */}
|
||||
{confirm && (
|
||||
</div>
|
||||
|
||||
{/* DB Migrate Confirmation Dialog */}
|
||||
<ConfirmDialog
|
||||
isOpen={showDbMigrateDialog}
|
||||
type="info"
|
||||
title={translate('::ListForms.ListForm.DbMigrate') || 'DB Migrate'}
|
||||
cancelText={translate('::Cancel')}
|
||||
confirmText={translate('::App.Platform.Execute') || 'Çalıştır'}
|
||||
onCancel={() => setShowDbMigrateDialog(false)}
|
||||
onClose={() => setShowDbMigrateDialog(false)}
|
||||
onConfirm={() => {
|
||||
setShowDbMigrateDialog(false)
|
||||
UiEvalService.ApiDbMigrate()
|
||||
}}
|
||||
>
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
{translate('::App.DbMigrate.ConfirmMessage') ||
|
||||
'Veritabanı migration işlemini başlatmak istediğinize emin misiniz?'}
|
||||
</p>
|
||||
</ConfirmDialog>
|
||||
|
||||
{/* Delete Confirm Dialog */}
|
||||
{confirm && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xl p-6 max-w-sm w-full mx-4">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
|
|
@ -239,7 +289,6 @@ const WizardFileManager = () => {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Button, FormItem, Input, Notification, Select, toast } from '@/components/ui'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/list-form/models'
|
||||
import { MenuDto } from '@/proxy/menus/models'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import navigationIcon from '@/proxy/menus/navigation-icon.config'
|
||||
|
|
@ -20,6 +19,7 @@ import {
|
|||
} from 'react-icons/fa'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { IconPickerField, MenuAddDialog } from '@/views/shared/MenuAddDialog'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/wizard/models'
|
||||
|
||||
// ─── Types (exported for Wizard.tsx) ─────────────────────────────────────────
|
||||
|
||||
|
|
@ -256,6 +256,19 @@ function TreeNode({
|
|||
|
||||
// ─── MenuTreeInline ───────────────────────────────────────────────────────────
|
||||
|
||||
/** Returns all ancestor codes of `code` in the flat rawItems list */
|
||||
function getAncestorCodes(rawItems: MenuItem[], code: string): Set<string> {
|
||||
const result = new Set<string>()
|
||||
let current = code
|
||||
for (let i = 0; i < 50; i++) {
|
||||
const item = rawItems.find((r) => r.code === current)
|
||||
if (!item?.parentCode) break
|
||||
result.add(item.parentCode)
|
||||
current = item.parentCode
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
interface MenuTreeInlineProps {
|
||||
value: string
|
||||
onChange: (code: string) => void
|
||||
|
|
@ -264,6 +277,7 @@ interface MenuTreeInlineProps {
|
|||
isLoading: boolean
|
||||
invalid?: boolean
|
||||
onReload: () => void
|
||||
initialExpanded?: Set<string>
|
||||
}
|
||||
|
||||
function MenuTreeInline({
|
||||
|
|
@ -274,8 +288,21 @@ function MenuTreeInline({
|
|||
isLoading,
|
||||
invalid,
|
||||
onReload,
|
||||
initialExpanded,
|
||||
}: MenuTreeInlineProps) {
|
||||
const [expanded, setExpanded] = useState<Set<string>>(new Set())
|
||||
const [expanded, setExpanded] = useState<Set<string>>(() => initialExpanded ?? new Set())
|
||||
|
||||
// When value changes (e.g. edit mode loads), expand ancestor nodes
|
||||
useEffect(() => {
|
||||
if (!value || rawItems.length === 0) return
|
||||
const ancestors = getAncestorCodes(rawItems, value)
|
||||
if (ancestors.size === 0) return
|
||||
setExpanded((prev) => {
|
||||
const next = new Set(prev)
|
||||
ancestors.forEach((c) => next.add(c))
|
||||
return next
|
||||
})
|
||||
}, [value, rawItems])
|
||||
const [editingCode, setEditingCode] = useState<string | null>(null)
|
||||
const [editingValue, setEditingValue] = useState('')
|
||||
const [saving, setSaving] = useState(false)
|
||||
|
|
@ -505,6 +532,7 @@ const WizardStep1 = ({
|
|||
isLoading={isLoadingMenu}
|
||||
invalid={!!(errors.menuParentCode && touched.menuParentCode)}
|
||||
onReload={onReloadMenu}
|
||||
initialExpanded={values.menuParentCode ? getAncestorCodes(rawMenuItems, values.menuParentCode) : undefined}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Button, Checkbox, FormItem, Input, Select } from '@/components/ui'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/list-form/models'
|
||||
import { SelectCommandTypeEnum } from '@/proxy/form/models'
|
||||
import type { DatabaseColumnDto, SqlObjectExplorerDto } from '@/proxy/sql-query-manager/models'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
|
|
@ -7,6 +6,7 @@ import { Field, FieldProps, FormikErrors, FormikTouched } from 'formik'
|
|||
import CreatableSelect from 'react-select/creatable'
|
||||
import { FaArrowLeft, FaArrowRight } from 'react-icons/fa'
|
||||
import { dbSourceTypeOptions, listFormDefaultLayoutOptions, selectCommandTypeOptions, sqlDataTypeToDbType } from '../edit/options'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/wizard/models'
|
||||
|
||||
// ─── Props ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Button } from '@/components/ui'
|
||||
import type { ListFormWizardDto } from '@/proxy/admin/list-form/models'
|
||||
import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models'
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
|
|
@ -14,6 +13,7 @@ import {
|
|||
} from 'react-icons/fa'
|
||||
import { WizardGroup } from './WizardStep3'
|
||||
import { dbSourceTypeOptions, selectCommandTypeOptions } from '../edit/options'
|
||||
import { ListFormWizardDto } from '@/proxy/admin/wizard/models'
|
||||
|
||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { getDataSources } from '@/services/data-source.service'
|
|||
import type { DataSourceDto } from '@/proxy/data-source'
|
||||
import type { SqlQueryExecutionResultDto } from '@/proxy/sql-query-manager/models'
|
||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||
import { FaDatabase, FaPlay, FaFileAlt, FaCopy } from 'react-icons/fa'
|
||||
import { FaDatabase, FaPlay, FaFileAlt, FaCopy, FaExclamationTriangle } from 'react-icons/fa'
|
||||
import { FaCheckCircle } from 'react-icons/fa'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import SqlObjectExplorer, { type SqlExplorerSelectedObject } from './SqlObjectExplorer'
|
||||
|
|
@ -1067,7 +1067,7 @@ GO`,
|
|||
<Button variant="plain" onClick={handleCancelTemplateReplace}>
|
||||
{translate('::Cancel')}
|
||||
</Button>
|
||||
<Button variant="solid" onClick={handleConfirmTemplateReplace}>
|
||||
<Button variant="solid" onClick={handleConfirmTemplateReplace} icon={<FaExclamationTriangle />} color="red-600">
|
||||
{translate('::App.Platform.Replace')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,27 @@ const Chart = React.lazy(() => import('./Chart'))
|
|||
const GanttView = React.lazy(() => import('./GanttView'))
|
||||
const SchedulerView = React.lazy(() => import('./SchedulerView'))
|
||||
|
||||
function isLayoutValid(dto: GridDto, layout: ListViewLayoutType | undefined): boolean {
|
||||
if (!layout || layout === 'grid') return true
|
||||
if (layout === 'pivot') return !!dto.gridOptions?.layoutDto?.pivot
|
||||
if (layout === 'chart') return !!dto.gridOptions?.layoutDto?.chart
|
||||
if (layout === 'tree')
|
||||
return !!(dto.gridOptions?.layoutDto?.tree && dto.gridOptions?.treeOptionDto?.parentIdExpr)
|
||||
if (layout === 'gantt')
|
||||
return !!(
|
||||
dto.gridOptions?.layoutDto?.gantt &&
|
||||
dto.gridOptions?.ganttOptionDto?.parentIdExpr &&
|
||||
dto.gridOptions?.ganttOptionDto?.titleExpr
|
||||
)
|
||||
if (layout === 'scheduler')
|
||||
return !!(
|
||||
dto.gridOptions?.layoutDto?.scheduler &&
|
||||
dto.gridOptions?.schedulerOptionDto?.textExpr &&
|
||||
dto.gridOptions?.schedulerOptionDto?.startDateExpr
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
const List: React.FC = () => {
|
||||
const { listFormCode = '' } = useParams()
|
||||
const [searchParams] = useSearchParams()
|
||||
|
|
@ -69,10 +90,10 @@ const List: React.FC = () => {
|
|||
if (!gridDto) return
|
||||
|
||||
const savedLayout = states.find((s) => s.listFormCode === listFormCode)?.layout
|
||||
|
||||
const defaultLayout = gridDto.gridOptions?.layoutDto?.defaultLayout
|
||||
|
||||
setViewMode(savedLayout ?? defaultLayout)
|
||||
const candidate = savedLayout ?? defaultLayout
|
||||
|
||||
setViewMode(isLayoutValid(gridDto, candidate) ? candidate : 'grid')
|
||||
}, [gridDto, states, listFormCode])
|
||||
|
||||
/* =======================
|
||||
|
|
|
|||
|
|
@ -262,6 +262,14 @@ const useFilters = ({
|
|||
})
|
||||
}
|
||||
|
||||
if (grdOpt?.columnOptionDto?.columnAutoWidth) {
|
||||
menus.push({
|
||||
text: translate('::ListForms.ListForm.FitColumns'),
|
||||
id: 'fitColumns',
|
||||
icon: 'columnchooser',
|
||||
})
|
||||
}
|
||||
|
||||
//Kullanicinin gridstate kaydi yapmasina izin verilmis ise gridState menu elemanlarini ekle
|
||||
if (grdOpt?.stateStoringDto?.enabled) {
|
||||
menus.push({
|
||||
|
|
@ -277,14 +285,6 @@ const useFilters = ({
|
|||
})
|
||||
}
|
||||
|
||||
if (grdOpt?.columnOptionDto?.columnAutoWidth) {
|
||||
menus.push({
|
||||
text: translate('::ListForms.ListForm.FitColumns'),
|
||||
id: 'fitColumns',
|
||||
icon: 'columnchooser',
|
||||
})
|
||||
}
|
||||
|
||||
if (checkPermission(gridDto?.gridOptions.permissionDto.i)) {
|
||||
menus.push({
|
||||
text: translate('::ListForms.ListForm.ImportManager'),
|
||||
|
|
|
|||
Loading…
Reference in a new issue