From a196e8489062ef954c79cfdb27f00a6957aaf62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Tue, 28 Jul 2026 21:36:37 +0300 Subject: [PATCH] =?UTF-8?q?WizardManager=20d=C3=BCzenlemesi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ListForms/Wizard/ListFormWizardDto.cs | 44 +- .../ListForms/ListFormWizardAppService.cs | 82 +- .../Seeds/WizardData/202607172226_Todo.json | 60 +- .../WizardData/202607281621_Approval.json | 59 +- .../Seeds/WizardData/202607281645_Gantt.json | 59 +- .../Seeds/WizardDataSeeder.cs | 60 +- ui/src/proxy/admin/wizard/models.ts | 50 +- ui/src/routes/route.constant.ts | 1 + ui/src/views/admin/listForm/wizard/Wizard.tsx | 601 +++++++------ .../admin/listForm/wizard/WizardStep10.tsx | 163 ++++ .../admin/listForm/wizard/WizardStep11.tsx | 779 +++++++++++++++++ .../admin/listForm/wizard/WizardStep2.tsx | 197 +---- .../admin/listForm/wizard/WizardStep7.tsx | 60 +- .../admin/listForm/wizard/WizardStep8.tsx | 809 ++---------------- .../admin/listForm/wizard/WizardStep9.tsx | 126 +++ 15 files changed, 1685 insertions(+), 1465 deletions(-) create mode 100644 ui/src/views/admin/listForm/wizard/WizardStep10.tsx create mode 100644 ui/src/views/admin/listForm/wizard/WizardStep11.tsx create mode 100644 ui/src/views/admin/listForm/wizard/WizardStep9.tsx diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/ListFormWizardDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/ListFormWizardDto.cs index f53e96fb..b5057fe5 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/ListFormWizardDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Wizard/ListFormWizardDto.cs @@ -52,45 +52,11 @@ public class ListFormWizardDto public string KeyFieldName { get; set; } public DbType KeyFieldDbSourceType { get; set; } - // Tree options (required when DefaultLayout = "tree") - public string TreeKeyExpr { get; set; } - public string TreeParentIdExpr { get; set; } - public bool TreeAutoExpandAll { get; set; } - - // Gantt options (required when DefaultLayout = "gantt") - public string GanttKeyExpr { get; set; } - public string GanttParentIdExpr { get; set; } - public bool GanttAutoExpandAll { get; set; } - public string GanttTitleExpr { get; set; } - public string GanttStartExpr { get; set; } - public string GanttEndExpr { get; set; } - public string GanttProgressExpr { get; set; } - - // Scheduler options (required when DefaultLayout = "scheduler") - public string SchedulerTextExpr { get; set; } - public string SchedulerStartDateExpr { get; set; } - public string SchedulerEndDateExpr { get; set; } - - // Todo options (required when DefaultLayout = "todo") - public string TodoTitleExpr { get; set; } - public string TodoStatusExpr { get; set; } - public string TodoDescriptionExpr { get; set; } - public string TodoDueDateExpr { get; set; } - public string TodoTagExpr { get; set; } - public string TodoAssigneeExpr { get; set; } - public string TodoPriorityExpr { get; set; } - public string TodoCompletedExpr { get; set; } - public string TodoOrderExpr { get; set; } - public string TodoStatusOrder { get; set; } - public bool TodoAllowDragging { get; set; } = true; - - // Workflow options (required when DefaultLayout = "workflow") - public string ApprovalUserFieldName { get; set; } - public string ApprovalDateFieldName { get; set; } - public string ApprovalStatusFieldName { get; set; } - public string ApprovalDescriptionFieldName { get; set; } - public bool ApprovalIsFilterUserName { get; set; } - public List Criteria { get; set; } = []; + public TreeOptionDto TreeOptionDto { get; set; } = new(); + public GanttOptionDto GanttOptionDto { get; set; } = new(); + public SchedulerOptionDto SchedulerOptionDto { get; set; } = new(); + public TodoOptionDto TodoOptionDto { get; set; } = new(); + public WorkflowDto WorkflowDto { get; set; } = new(); public List Groups { get; set; } = new(); public List SubForms { get; set; } = new(); diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs index 05849988..f669d05c 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs @@ -264,18 +264,11 @@ public class ListFormWizardAppService( var tableColumns = await GetTableColumnNamesAsync(input.DataSourceCode, input.SelectCommandType, input.SelectCommand); var isDeleted = tableColumns.Contains("IsDeleted"); var isCreated = tableColumns.Contains("CreatorId"); - input.Criteria ??= []; - EnsureUniqueWorkflowCriteriaTitles(input.Criteria); - NormalizeWorkflowCriteriaIds(listFormCode, input.Criteria); - var workflow = new WorkflowDto - { - ApprovalUserFieldName = input.ApprovalUserFieldName, - ApprovalIsFilterUserName = input.ApprovalIsFilterUserName, - ApprovalDateFieldName = input.ApprovalDateFieldName, - ApprovalStatusFieldName = input.ApprovalStatusFieldName, - ApprovalDescriptionFieldName = input.ApprovalDescriptionFieldName, - Criteria = input.Criteria, - }; + input.WorkflowDto ??= new WorkflowDto(); + input.WorkflowDto.Criteria ??= []; + EnsureUniqueWorkflowCriteriaTitles(input.WorkflowDto.Criteria); + NormalizeWorkflowCriteriaIds(listFormCode, input.WorkflowDto.Criteria); + var workflow = input.WorkflowDto; await repoListForm.InsertAsync(new ListForm { @@ -283,7 +276,7 @@ public class ListFormWizardAppService( PageSize = 10, ExportJson = WizardConsts.DefaultExportJson, IsSubForm = false, - ShowNote = input.SubForms.Count > 0 || input.Criteria.Count > 0, + ShowNote = input.SubForms.Count > 0 || workflow.Criteria.Count > 0, LayoutJson = WizardConsts.DefaultLayoutJson(input.DefaultLayout, input.Grid, input.Card, input.Pivot, input.Tree, input.Chart, input.Gantt, input.Scheduler, input.Todo), CultureName = LanguageCodes.En, ListFormCode = input.ListFormCode, @@ -304,7 +297,7 @@ public class ListFormWizardAppService( HeaderFilterJson = WizardConsts.DefaultHeaderFilterJson(), SearchPanelJson = WizardConsts.DefaultSearchPanelJson(), GroupPanelJson = WizardConsts.DefaultGroupPanelJson(), - SelectionJson = WizardConsts.DefaultSelectionSingleJson(input.Criteria.Count > 0 ? PlatformConsts.GridOptions.SelectionModeSingle : PlatformConsts.GridOptions.SelectionModeNone), + SelectionJson = WizardConsts.DefaultSelectionSingleJson(workflow.Criteria.Count > 0 ? PlatformConsts.GridOptions.SelectionModeSingle : PlatformConsts.GridOptions.SelectionModeNone), ColumnOptionJson = WizardConsts.DefaultColumnOptionJson(), PermissionJson = WizardConsts.DefaultPermissionJson(code), DeleteCommand = isDeleted ? WizardConsts.DefaultDeleteCommand(input.SelectCommand) : null, @@ -315,52 +308,23 @@ public class ListFormWizardAppService( EditingFormJson = editingFormDtos.Count > 0 ? JsonSerializer.Serialize(editingFormDtos) : null, SubFormsJson = input.SubForms.Count > 0 ? JsonSerializer.Serialize(input.SubForms) : null, WidgetsJson = input.Widgets.Count > 0 ? JsonSerializer.Serialize(input.Widgets) : null, - WorkflowJson = HasWorkflow(workflow, input.Criteria) ? JsonSerializer.Serialize(workflow) : null, - TreeOptionJson = (input.Tree || input.DefaultLayout == "tree") && !string.IsNullOrEmpty(input.TreeParentIdExpr) - ? JsonSerializer.Serialize(new TreeOptionDto - { - KeyExpr = input.TreeKeyExpr, - ParentIdExpr = input.TreeParentIdExpr, - AutoExpandAll = input.TreeAutoExpandAll, - }) + WorkflowJson = HasWorkflow(workflow) ? JsonSerializer.Serialize(workflow) : null, + TreeOptionJson = (input.Tree || input.DefaultLayout == "tree") && + !string.IsNullOrEmpty(input.TreeOptionDto?.ParentIdExpr) + ? JsonSerializer.Serialize(input.TreeOptionDto) : null, - GanttOptionJson = (input.Gantt || input.DefaultLayout == "gantt") && !string.IsNullOrEmpty(input.GanttParentIdExpr) - ? JsonSerializer.Serialize(new GanttOptionDto - { - KeyExpr = input.GanttKeyExpr, - ParentIdExpr = input.GanttParentIdExpr, - AutoExpandAll = input.GanttAutoExpandAll, - TitleExpr = input.GanttTitleExpr, - StartExpr = input.GanttStartExpr, - EndExpr = input.GanttEndExpr, - ProgressExpr = input.GanttProgressExpr, - }) + GanttOptionJson = (input.Gantt || input.DefaultLayout == "gantt") && + !string.IsNullOrEmpty(input.GanttOptionDto?.ParentIdExpr) + ? JsonSerializer.Serialize(input.GanttOptionDto) : null, - SchedulerOptionJson = (input.Scheduler || input.DefaultLayout == "scheduler") && !string.IsNullOrEmpty(input.SchedulerTextExpr) - ? JsonSerializer.Serialize(new SchedulerOptionDto - { - TextExpr = input.SchedulerTextExpr, - StartDateExpr = input.SchedulerStartDateExpr, - EndDateExpr = input.SchedulerEndDateExpr, - }) + SchedulerOptionJson = (input.Scheduler || input.DefaultLayout == "scheduler") && + !string.IsNullOrEmpty(input.SchedulerOptionDto?.TextExpr) + ? JsonSerializer.Serialize(input.SchedulerOptionDto) : null, TodoOptionJson = (input.Todo || input.DefaultLayout == "todo") && - !string.IsNullOrEmpty(input.TodoTitleExpr) && - !string.IsNullOrEmpty(input.TodoStatusExpr) - ? JsonSerializer.Serialize(new TodoOptionDto - { - TitleExpr = input.TodoTitleExpr, - StatusExpr = input.TodoStatusExpr, - DescriptionExpr = input.TodoDescriptionExpr, - DueDateExpr = input.TodoDueDateExpr, - TagExpr = input.TodoTagExpr, - AssigneeExpr = input.TodoAssigneeExpr, - PriorityExpr = input.TodoPriorityExpr, - CompletedExpr = input.TodoCompletedExpr, - OrderExpr = input.TodoOrderExpr, - StatusOrder = input.TodoStatusOrder, - AllowDragging = input.TodoAllowDragging, - }) + !string.IsNullOrEmpty(input.TodoOptionDto?.TitleExpr) && + !string.IsNullOrEmpty(input.TodoOptionDto?.StatusExpr) + ? JsonSerializer.Serialize(input.TodoOptionDto) : null, }, autoSave: true); @@ -409,7 +373,7 @@ public class ListFormWizardAppService( } } - foreach (var criteria in input.Criteria) + foreach (var criteria in workflow.Criteria) { if (string.IsNullOrWhiteSpace(criteria.Id)) { @@ -443,12 +407,12 @@ public class ListFormWizardAppService( await SaveWizardSeedFileAsync(input, isDeleted, isCreated, inserted); } - private static bool HasWorkflow(WorkflowDto workflow, List criteria) + private static bool HasWorkflow(WorkflowDto workflow) { return workflow != null && ( !string.IsNullOrWhiteSpace(workflow.ApprovalUserFieldName) || !string.IsNullOrWhiteSpace(workflow.ApprovalStatusFieldName) || - criteria.Count > 0 + workflow.Criteria.Count > 0 ); } diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607172226_Todo.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607172226_Todo.json index db30f65e..4816f5ae 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607172226_Todo.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607172226_Todo.json @@ -15,10 +15,10 @@ "Grid": true, "Card": true, "Pivot": true, - "Tree": true, "Chart": true, - "Gantt": true, - "Scheduler": true, + "Tree": false, + "Gantt": false, + "Scheduler": false, "Todo": true, "LanguageTextMenuEn": "Todo", "LanguageTextMenuTr": "\u0130\u015Fler", @@ -39,36 +39,30 @@ "SelectCommand": "Pro_T_Todo", "KeyFieldName": "Id", "KeyFieldDbSourceType": 9, - "TreeKeyExpr": "", - "TreeParentIdExpr": "", - "TreeAutoExpandAll": false, - "GanttKeyExpr": "", - "GanttParentIdExpr": "", - "GanttAutoExpandAll": false, - "GanttTitleExpr": "", - "GanttStartExpr": "", - "GanttEndExpr": "", - "GanttProgressExpr": "", - "SchedulerTextExpr": "", - "SchedulerStartDateExpr": "", - "SchedulerEndDateExpr": "", - "TodoTitleExpr": "Title", - "TodoStatusExpr": "Status", - "TodoDescriptionExpr": "Description", - "TodoDueDateExpr": "DueDate", - "TodoTagExpr": "Tags", - "TodoAssigneeExpr": "Assignees", - "TodoPriorityExpr": "Priority", - "TodoCompletedExpr": "Completed", - "TodoOrderExpr": "SortOrder", - "TodoStatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging", - "TodoAllowDragging": true, - "ApprovalUserFieldName": "", - "ApprovalDateFieldName": "", - "ApprovalStatusFieldName": "", - "ApprovalDescriptionFieldName": "", - "ApprovalIsFilterUserName": false, - "Criteria": [], + "TreeOptionDto": {}, + "GanttOptionDto": {}, + "SchedulerOptionDto": {}, + "TodoOptionDto": { + "TitleExpr": "Title", + "StatusExpr": "Status", + "DescriptionExpr": "Description", + "DueDateExpr": "DueDate", + "TagExpr": "Tags", + "AssigneeExpr": "Assignees", + "PriorityExpr": "Priority", + "CompletedExpr": "Completed", + "OrderExpr": "SortOrder", + "StatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging", + "AllowDragging": true + }, + "WorkflowDto": { + "ApprovalUserFieldName": "", + "ApprovalDateFieldName": "", + "ApprovalStatusFieldName": "", + "ApprovalDescriptionFieldName": "", + "ApprovalIsFilterUserName": false, + "Criteria": [] + }, "Groups": [ { "Caption": "", diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281621_Approval.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281621_Approval.json index 870bed9c..93259614 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281621_Approval.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281621_Approval.json @@ -15,10 +15,10 @@ "Grid": true, "Card": true, "Pivot": true, - "Tree": true, "Chart": true, - "Gantt": true, - "Scheduler": true, + "Tree": true, + "Gantt": false, + "Scheduler": false, "Todo": false, "LanguageTextMenuEn": "Approval", "LanguageTextMenuTr": "Onaylama", @@ -39,36 +39,24 @@ "SelectCommand": "Pro_T_Approval", "KeyFieldName": "Id", "KeyFieldDbSourceType": 9, - "TreeKeyExpr": "Title", - "TreeParentIdExpr": "ParentTitle", - "TreeAutoExpandAll": true, - "GanttKeyExpr": "", - "GanttParentIdExpr": "", - "GanttAutoExpandAll": false, - "GanttTitleExpr": "", - "GanttStartExpr": "", - "GanttEndExpr": "", - "GanttProgressExpr": "", - "SchedulerTextExpr": "", - "SchedulerStartDateExpr": "", - "SchedulerEndDateExpr": "", - "TodoTitleExpr": "", - "TodoStatusExpr": "", - "TodoDescriptionExpr": "", - "TodoDueDateExpr": "", - "TodoTagExpr": "", - "TodoAssigneeExpr": "", - "TodoPriorityExpr": "", - "TodoCompletedExpr": "", - "TodoOrderExpr": "", - "TodoStatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging", - "TodoAllowDragging": true, - "ApprovalUserFieldName": "ApprovalUserName", - "ApprovalDateFieldName": "ApprovalDate", - "ApprovalStatusFieldName": "ApprovalStatus", - "ApprovalDescriptionFieldName": "ApprovalDescription", - "ApprovalIsFilterUserName": false, - "Criteria": [ + "TreeOptionDto": { + "KeyExpr": "Title", + "ParentIdExpr": "ParentTitle", + "AutoExpandAll": true + }, + "GanttOptionDto": {}, + "SchedulerOptionDto": {}, + "TodoOptionDto": { + "StatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging", + "AllowDragging": true + }, + "WorkflowDto": { + "ApprovalUserFieldName": "ApprovalUserName", + "ApprovalDateFieldName": "ApprovalDate", + "ApprovalStatusFieldName": "ApprovalStatus", + "ApprovalDescriptionFieldName": "ApprovalDescription", + "ApprovalIsFilterUserName": false, + "Criteria": [ { "ListFormCode": "App.Wizard.Approval", "Kind": "Start", @@ -141,7 +129,8 @@ "CompareOutcomes": [], "Id": "App.Wizard.Approval-N004" } - ], + ] + }, "Groups": [ { "Caption": "", @@ -296,4 +285,4 @@ ], "DataSourceCodes": [] } -} \ No newline at end of file +} diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281645_Gantt.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281645_Gantt.json index 81213534..1d48f0b2 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281645_Gantt.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardData/202607281645_Gantt.json @@ -15,10 +15,10 @@ "Grid": true, "Card": true, "Pivot": true, - "Tree": true, "Chart": true, + "Tree": false, "Gantt": true, - "Scheduler": true, + "Scheduler": false, "Todo": false, "LanguageTextMenuEn": "Gantt", "LanguageTextMenuTr": "Gantt", @@ -39,36 +39,29 @@ "SelectCommand": "Pro_D_Gantt", "KeyFieldName": "Id", "KeyFieldDbSourceType": 9, - "TreeKeyExpr": "", - "TreeParentIdExpr": "", - "TreeAutoExpandAll": false, - "GanttKeyExpr": "Id", - "GanttParentIdExpr": "ParentId", - "GanttAutoExpandAll": true, - "GanttTitleExpr": "Title", - "GanttStartExpr": "StartDate", - "GanttEndExpr": "EndDate", - "GanttProgressExpr": "Progress", - "SchedulerTextExpr": "", - "SchedulerStartDateExpr": "", - "SchedulerEndDateExpr": "", - "TodoTitleExpr": "", - "TodoStatusExpr": "", - "TodoDescriptionExpr": "", - "TodoDueDateExpr": "", - "TodoTagExpr": "", - "TodoAssigneeExpr": "", - "TodoPriorityExpr": "", - "TodoCompletedExpr": "", - "TodoOrderExpr": "", - "TodoStatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging", - "TodoAllowDragging": true, - "ApprovalUserFieldName": "", - "ApprovalDateFieldName": "", - "ApprovalStatusFieldName": "", - "ApprovalDescriptionFieldName": "", - "ApprovalIsFilterUserName": false, - "Criteria": [], + "TreeOptionDto": {}, + "GanttOptionDto": { + "KeyExpr": "Id", + "ParentIdExpr": "ParentId", + "AutoExpandAll": true, + "TitleExpr": "Title", + "StartExpr": "StartDate", + "EndExpr": "EndDate", + "ProgressExpr": "Progress" + }, + "SchedulerOptionDto": {}, + "TodoOptionDto": { + "StatusOrder": "Backlog, Ready to Start, In Progress, Code Review, Testing, Staging", + "AllowDragging": true + }, + "WorkflowDto": { + "ApprovalUserFieldName": "", + "ApprovalDateFieldName": "", + "ApprovalStatusFieldName": "", + "ApprovalDescriptionFieldName": "", + "ApprovalIsFilterUserName": false, + "Criteria": [] + }, "Groups": [ { "Caption": "", @@ -205,4 +198,4 @@ ], "DataSourceCodes": [] } -} \ No newline at end of file +} diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs index 96955ff3..4329f8ca 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/WizardDataSeeder.cs @@ -134,17 +134,10 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency var isCreated = seedFile.IsCreatedField; input.SubForms ??= new List(); input.Widgets ??= new List(); - input.Criteria ??= []; - EnsureUniqueWorkflowCriteriaTitles(input.Criteria); - var workflow = new WorkflowDto - { - ApprovalUserFieldName = input.ApprovalUserFieldName, - ApprovalIsFilterUserName = input.ApprovalIsFilterUserName, - ApprovalDateFieldName = input.ApprovalDateFieldName, - ApprovalStatusFieldName = input.ApprovalStatusFieldName, - ApprovalDescriptionFieldName = input.ApprovalDescriptionFieldName, - Criteria = input.Criteria, - }; + input.WorkflowDto ??= new WorkflowDto(); + input.WorkflowDto.Criteria ??= []; + EnsureUniqueWorkflowCriteriaTitles(input.WorkflowDto.Criteria); + var workflow = input.WorkflowDto; var wizardName = input.WizardName.Trim(); var code = string.IsNullOrWhiteSpace(input.MenuCode) @@ -153,7 +146,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency var listFormCode = string.IsNullOrWhiteSpace(input.ListFormCode) ? code : input.ListFormCode.Trim(); - NormalizeWorkflowCriteriaIds(listFormCode, input.Criteria); + NormalizeWorkflowCriteriaIds(listFormCode, workflow.Criteria); var titleLangKey = $"{listFormCode}.Title"; var nameLangKey = code; var descLangKey = $"{listFormCode}.Desc"; @@ -386,7 +379,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency PageSize = 10, ExportJson = WizardConsts.DefaultExportJson, IsSubForm = false, - ShowNote = input.SubForms.Count > 0 || input.Criteria.Count > 0, + ShowNote = input.SubForms.Count > 0 || workflow.Criteria.Count > 0, LayoutJson = WizardConsts.DefaultLayoutJson(input.DefaultLayout, input.Grid, input.Card, input.Pivot, input.Tree, input.Chart, input.Gantt, input.Scheduler, input.Todo), CultureName = LanguageCodes.En, ListFormCode = input.ListFormCode, @@ -407,7 +400,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency HeaderFilterJson = WizardConsts.DefaultHeaderFilterJson(), SearchPanelJson = WizardConsts.DefaultSearchPanelJson(), GroupPanelJson = WizardConsts.DefaultGroupPanelJson(), - SelectionJson = WizardConsts.DefaultSelectionSingleJson(input.Criteria.Count > 0 ? GridOptions.SelectionModeSingle : GridOptions.SelectionModeNone), + SelectionJson = WizardConsts.DefaultSelectionSingleJson(workflow.Criteria.Count > 0 ? GridOptions.SelectionModeSingle : GridOptions.SelectionModeNone), ColumnOptionJson = WizardConsts.DefaultColumnOptionJson(), PermissionJson = WizardConsts.DefaultPermissionJson(code), DeleteCommand = isDeleted ? WizardConsts.DefaultDeleteCommand(input.SelectCommand) : null, @@ -422,24 +415,23 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency EditingFormJson = editingFormDtos.Count > 0 ? JsonSerializer.Serialize(editingFormDtos) : null, SubFormsJson = input.SubForms.Count > 0 ? JsonSerializer.Serialize(input.SubForms) : null, WidgetsJson = input.Widgets.Count > 0 ? JsonSerializer.Serialize(input.Widgets) : null, - WorkflowJson = HasWorkflow(workflow, input.Criteria) ? JsonSerializer.Serialize(workflow) : null, + WorkflowJson = HasWorkflow(workflow) ? JsonSerializer.Serialize(workflow) : null, + TreeOptionJson = (input.Tree || input.DefaultLayout == "tree") && + !string.IsNullOrEmpty(input.TreeOptionDto?.ParentIdExpr) + ? JsonSerializer.Serialize(input.TreeOptionDto) + : null, + GanttOptionJson = (input.Gantt || input.DefaultLayout == "gantt") && + !string.IsNullOrEmpty(input.GanttOptionDto?.ParentIdExpr) + ? JsonSerializer.Serialize(input.GanttOptionDto) + : null, + SchedulerOptionJson = (input.Scheduler || input.DefaultLayout == "scheduler") && + !string.IsNullOrEmpty(input.SchedulerOptionDto?.TextExpr) + ? JsonSerializer.Serialize(input.SchedulerOptionDto) + : null, TodoOptionJson = (input.Todo || input.DefaultLayout == "todo") && - !string.IsNullOrEmpty(input.TodoTitleExpr) && - !string.IsNullOrEmpty(input.TodoStatusExpr) - ? JsonSerializer.Serialize(new TodoOptionDto - { - TitleExpr = input.TodoTitleExpr, - StatusExpr = input.TodoStatusExpr, - DescriptionExpr = input.TodoDescriptionExpr, - DueDateExpr = input.TodoDueDateExpr, - TagExpr = input.TodoTagExpr, - AssigneeExpr = input.TodoAssigneeExpr, - PriorityExpr = input.TodoPriorityExpr, - CompletedExpr = input.TodoCompletedExpr, - OrderExpr = input.TodoOrderExpr, - StatusOrder = input.TodoStatusOrder, - AllowDragging = input.TodoAllowDragging, - }) + !string.IsNullOrEmpty(input.TodoOptionDto?.TitleExpr) && + !string.IsNullOrEmpty(input.TodoOptionDto?.StatusExpr) + ? JsonSerializer.Serialize(input.TodoOptionDto) : null, }, autoSave: true); @@ -493,7 +485,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency } } - foreach (var criteria in input.Criteria) + foreach (var criteria in workflow.Criteria) { if (string.IsNullOrWhiteSpace(criteria.Id)) { @@ -540,14 +532,14 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency menuParent.ShortName); } - private static bool HasWorkflow(WorkflowDto workflow, List criteria) + private static bool HasWorkflow(WorkflowDto workflow) { return workflow != null && ( !string.IsNullOrWhiteSpace(workflow.ApprovalUserFieldName) || !string.IsNullOrWhiteSpace(workflow.ApprovalDateFieldName) || !string.IsNullOrWhiteSpace(workflow.ApprovalStatusFieldName) || !string.IsNullOrWhiteSpace(workflow.ApprovalDescriptionFieldName) || - (criteria?.Count ?? 0) > 0 + workflow.Criteria.Count > 0 ); } diff --git a/ui/src/proxy/admin/wizard/models.ts b/ui/src/proxy/admin/wizard/models.ts index f6851dd7..1000f601 100644 --- a/ui/src/proxy/admin/wizard/models.ts +++ b/ui/src/proxy/admin/wizard/models.ts @@ -1,7 +1,11 @@ import { - ListFormWorkflowCriteriaDto, + GanttOptionDto, + SchedulerOptionDto, SubFormDto, + TodoOptionDto, + TreeOptionDto, WidgetEditDto, + WorkflowDto, SelectCommandTypeEnum, } from '@/proxy/form/models' import { ListViewLayoutType } from '@/views/admin/listForm/edit/types' @@ -66,45 +70,11 @@ export interface ListFormWizardDto { keyFieldName: string keyFieldDbSourceType: number - // Tree options (required when defaultLayout = 'tree') - treeKeyExpr?: string - treeParentIdExpr?: string - treeAutoExpandAll?: boolean - - // Gantt options (required when defaultLayout = 'gantt') - ganttKeyExpr?: string - ganttParentIdExpr?: string - ganttAutoExpandAll?: boolean - ganttTitleExpr?: string - ganttStartExpr?: string - ganttEndExpr?: string - ganttProgressExpr?: string - - // Scheduler options (required when defaultLayout = 'scheduler') - schedulerTextExpr?: string - schedulerStartDateExpr?: string - schedulerEndDateExpr?: string - - // Todo options (required when defaultLayout = 'todo') - todoTitleExpr: string - todoStatusExpr: string - todoDescriptionExpr: string - todoDueDateExpr: string - todoTagExpr: string - todoAssigneeExpr: string - todoPriorityExpr: string - todoCompletedExpr: string - todoOrderExpr: string - todoStatusOrder: string - todoAllowDragging: boolean - - // Workflow options (required when defaultLayout = 'workflow') - approvalUserFieldName: string - approvalDateFieldName: string - approvalStatusFieldName: string - approvalDescriptionFieldName: string - approvalIsFilterUserName: boolean - criteria: ListFormWorkflowCriteriaDto[] + treeOptionDto: TreeOptionDto + ganttOptionDto: GanttOptionDto + schedulerOptionDto: SchedulerOptionDto + todoOptionDto: TodoOptionDto + workflowDto: WorkflowDto groups?: ListFormWizardColumnGroupDto[] subForms?: SubFormDto[] diff --git a/ui/src/routes/route.constant.ts b/ui/src/routes/route.constant.ts index 847ccbd4..2a6e14f7 100644 --- a/ui/src/routes/route.constant.ts +++ b/ui/src/routes/route.constant.ts @@ -31,6 +31,7 @@ export const ROUTES_ENUM = { menuManager: '/admin/menuManager', listFormManagement: { wizard: '/admin/listform/wizard', + wizardManager: '/admin/listform/wizardManager', edit: '/admin/listform/edit/:listFormCode', }, forumManagement: '/admin/forumManagement', diff --git a/ui/src/views/admin/listForm/wizard/Wizard.tsx b/ui/src/views/admin/listForm/wizard/Wizard.tsx index 259836f1..c2a43516 100644 --- a/ui/src/views/admin/listForm/wizard/Wizard.tsx +++ b/ui/src/views/admin/listForm/wizard/Wizard.tsx @@ -8,6 +8,7 @@ import { useEffect, useRef, useState } from 'react' import { Helmet } from 'react-helmet' import { useLocation, useNavigate } from 'react-router-dom' import * as Yup from 'yup' +import { FaFolderOpen } from 'react-icons/fa' import { getMenus } from '@/services/menu.service' import { getPermissions } from '@/services/identity.service' import { getDataSources } from '@/services/data-source.service' @@ -25,6 +26,9 @@ import WizardStep2 from './WizardStep2' import WizardStep3, { WizardGroup, WizardGroupItem } from './WizardStep3' import WizardStep7 from './WizardStep7' import WizardStep8 from './WizardStep8' +import WizardStep9 from './WizardStep9' +import WizardStep10 from './WizardStep10' +import WizardStep11 from './WizardStep11' import WizardStep4 from './WizardStep4' import WizardStep5 from './WizardStep5' import WizardStep6 from './WizardStep6' @@ -60,22 +64,81 @@ const initialValues: ListFormWizardDto = { grid: true, card: true, pivot: true, - tree: true, chart: true, - gantt: true, - scheduler: true, + tree: false, + gantt: false, + scheduler: false, todo: false, - todoTitleExpr: '', - todoStatusExpr: '', - todoDescriptionExpr: '', - todoDueDateExpr: '', - todoTagExpr: '', - todoAssigneeExpr: '', - todoPriorityExpr: '', - todoCompletedExpr: '', - todoOrderExpr: '', - todoStatusOrder: 'Backlog, Ready to Start, In Progress, Code Review, Testing, Staging', - todoAllowDragging: true, + treeOptionDto: { + keyExpr: '', + parentIdExpr: '', + hasItemsExpr: '', + rootValue: '', + autoExpandAll: false, + recursiveSelection: false, + }, + ganttOptionDto: { + keyExpr: '', + parentIdExpr: '', + hasItemsExpr: '', + rootValue: '', + autoExpandAll: false, + recursiveSelection: false, + titleExpr: '', + startExpr: '', + endExpr: '', + progressExpr: '', + scaleType: 'weeks', + allowEditing: false, + allowTaskAdding: false, + allowTaskUpdating: false, + allowTaskDeleting: false, + allowDependencyAdding: false, + allowDependencyDeleting: false, + allowResourceAdding: false, + allowResourceDeleting: false, + }, + schedulerOptionDto: { + textExpr: '', + startDateExpr: '', + endDateExpr: '', + allDayExpr: '', + recurrenceRuleExpr: '', + recurrenceExceptionExpr: '', + startDayHour: 8, + endDayHour: 18, + defaultView: 'week', + showAllDayPanel: true, + cellDuration: 30, + firstDayOfWeek: 1, + crossScrollingEnabled: false, + allowResizing: false, + allowDragging: false, + allowAdding: false, + allowEditing: false, + allowDeleting: false, + }, + todoOptionDto: { + titleExpr: '', + statusExpr: '', + descriptionExpr: '', + dueDateExpr: '', + tagExpr: '', + assigneeExpr: '', + priorityExpr: '', + completedExpr: '', + orderExpr: '', + statusOrder: 'Backlog, Ready to Start, In Progress, Code Review, Testing, Staging', + allowDragging: true, + }, + workflowDto: { + approvalUserFieldName: '', + approvalDateFieldName: '', + approvalStatusFieldName: '', + approvalDescriptionFieldName: '', + approvalIsFilterUserName: false, + criteria: [], + }, languageTextMenuEn: '', languageTextMenuTr: '', languageTextTitleEn: '', @@ -95,27 +158,8 @@ const initialValues: ListFormWizardDto = { selectCommand: '', keyFieldName: '', keyFieldDbSourceType: DbTypeEnum.Int32, - treeKeyExpr: '', - treeParentIdExpr: '', - treeAutoExpandAll: false, - ganttKeyExpr: '', - ganttParentIdExpr: '', - ganttAutoExpandAll: false, - ganttTitleExpr: '', - ganttStartExpr: '', - ganttEndExpr: '', - ganttProgressExpr: '', - schedulerTextExpr: '', - schedulerStartDateExpr: '', - schedulerEndDateExpr: '', subForms: [], widgets: [], - approvalUserFieldName: '', - approvalDateFieldName: '', - approvalStatusFieldName: '', - approvalDescriptionFieldName: '', - approvalIsFilterUserName: false, - criteria: [], } const step1ValidationSchema = Yup.object().shape({ @@ -147,26 +191,7 @@ const step2ValidationSchema = Yup.object().shape({ confirmDelete: Yup.boolean(), }) -const todoValidationSchema = Yup.object().shape({ - todoTitleExpr: Yup.string() - .trim() - .when('todo', { - is: true, - then: (schema) => schema.required(), - otherwise: (schema) => schema.notRequired(), - }), - todoStatusExpr: Yup.string() - .trim() - .when('todo', { - is: true, - then: (schema) => schema.required(), - otherwise: (schema) => schema.notRequired(), - }), -}) - -const listFormValidationSchema = step1ValidationSchema - .concat(step2ValidationSchema) - .concat(todoValidationSchema) +const listFormValidationSchema = step1ValidationSchema.concat(step2ValidationSchema) // ─── Wizard ─────────────────────────────────────────────────────────────────── @@ -444,19 +469,11 @@ const Wizard = () => { gantt: w.gantt ?? true, scheduler: w.scheduler ?? true, todo: w.todo ?? true, - todoTitleExpr: w.todoTitleExpr ?? '', - todoStatusExpr: w.todoStatusExpr ?? '', - todoDescriptionExpr: w.todoDescriptionExpr ?? '', - todoDueDateExpr: w.todoDueDateExpr ?? '', - todoTagExpr: w.todoTagExpr ?? '', - todoAssigneeExpr: w.todoAssigneeExpr ?? '', - todoPriorityExpr: w.todoPriorityExpr ?? '', - todoCompletedExpr: w.todoCompletedExpr ?? '', - todoOrderExpr: w.todoOrderExpr ?? '', - todoStatusOrder: - w.todoStatusOrder ?? - 'Backlog, Ready to Start, In Progress, Code Review, Testing, Staging', - todoAllowDragging: w.todoAllowDragging ?? true, + treeOptionDto: w.treeOptionDto ?? initialValues.treeOptionDto, + ganttOptionDto: w.ganttOptionDto ?? initialValues.ganttOptionDto, + schedulerOptionDto: w.schedulerOptionDto ?? initialValues.schedulerOptionDto, + todoOptionDto: w.todoOptionDto ?? initialValues.todoOptionDto, + workflowDto: w.workflowDto ?? initialValues.workflowDto, languageTextMenuEn: w.languageTextMenuEn ?? '', languageTextMenuTr: w.languageTextMenuTr ?? '', languageTextTitleEn: w.languageTextTitleEn ?? '', @@ -476,27 +493,8 @@ const Wizard = () => { selectCommand: w.selectCommand ?? '', keyFieldName: w.keyFieldName ?? '', keyFieldDbSourceType: w.keyFieldDbSourceType ?? DbTypeEnum.Int32, - treeKeyExpr: w.treeKeyExpr ?? '', - treeParentIdExpr: w.treeParentIdExpr ?? '', - treeAutoExpandAll: w.treeAutoExpandAll ?? false, - ganttKeyExpr: w.ganttKeyExpr ?? '', - ganttParentIdExpr: w.ganttParentIdExpr ?? '', - ganttAutoExpandAll: w.ganttAutoExpandAll ?? false, - ganttTitleExpr: w.ganttTitleExpr ?? '', - ganttStartExpr: w.ganttStartExpr ?? '', - ganttEndExpr: w.ganttEndExpr ?? '', - ganttProgressExpr: w.ganttProgressExpr ?? '', - schedulerTextExpr: w.schedulerTextExpr ?? '', - schedulerStartDateExpr: w.schedulerStartDateExpr ?? '', - schedulerEndDateExpr: w.schedulerEndDateExpr ?? '', subForms: w.subForms ?? [], widgets: w.widgets ?? [], - approvalUserFieldName: w.approvalUserFieldName ?? '', - approvalDateFieldName: w.approvalDateFieldName ?? '', - approvalStatusFieldName: w.approvalStatusFieldName ?? '', - approvalDescriptionFieldName: w.approvalDescriptionFieldName ?? '', - approvalIsFilterUserName: w.approvalIsFilterUserName ?? false, - criteria: w.criteria ?? [], }) // Queue column load to run once dbObjects is available @@ -551,15 +549,8 @@ const Wizard = () => { setSubForms(w.subForms ?? []) setWidgets(w.widgets ?? []) - setWorkflow({ - approvalUserFieldName: w.approvalUserFieldName ?? '', - approvalDateFieldName: w.approvalDateFieldName ?? '', - approvalStatusFieldName: w.approvalStatusFieldName ?? '', - approvalDescriptionFieldName: w.approvalDescriptionFieldName ?? '', - approvalIsFilterUserName: w.approvalIsFilterUserName ?? false, - criteria: w.criteria ?? [], - }) - setCriteria(w.criteria ?? []) + setWorkflow(w.workflowDto ?? initialValues.workflowDto) + setCriteria(w.workflowDto?.criteria ?? []) } catch { toast.push( @@ -786,12 +777,10 @@ const Wizard = () => { })), subForms, widgets, - approvalUserFieldName: workflow.approvalUserFieldName, - approvalDateFieldName: workflow.approvalDateFieldName, - approvalStatusFieldName: workflow.approvalStatusFieldName, - approvalDescriptionFieldName: workflow.approvalDescriptionFieldName, - approvalIsFilterUserName: workflow.approvalIsFilterUserName, - criteria, + workflowDto: { + ...workflow, + criteria, + }, }) // ✅ sonra config çek @@ -822,26 +811,6 @@ const Wizard = () => { defaultTitle={APP_NAME} /> -
- - - - - - - - - - -
- {isLoadingEditData && (

{translate('::App.Loading') || 'Loading...'} @@ -856,150 +825,268 @@ const Wizard = () => { setSubmitting(false) }} > - {({ touched, errors, values }) => ( -

- = 2 ? undefined : 'sm'}> - {/* ─── Step 1: Basic Info ─────────────────────────────── */} - {currentStep === 0 && ( - { - formikRef.current?.setFieldValue('menuParentCode', '') - formikRef.current?.setFieldValue('menuParentShortName', '') - formikRef.current?.setFieldValue('menuParentIcon', '') - }} - onMenuCreated={handleMenuCreated} - onReloadMenu={getMenuList} - permissionGroupList={permissionGroupList} - isLoadingPermissionGroup={isLoadingPermissionGroup} - onNext={handleNext} - translate={translate} - /> - )} + {({ touched, errors, values }) => { + const activeSteps = [ + { id: 0, title: translate('::ListForms.Wizard.MenuInfo') || 'Menu Info' }, + { + id: 1, + title: translate('::ListForms.Wizard.ListFormSettings') || 'List Form Settings', + }, + { + id: 2, + title: translate('::ListForms.Wizard.ListFormFields') || 'List Form Fields', + }, + { + id: 3, + title: translate('::ListForms.ListFormEdit.SubForms') || 'Sub Forms', + }, + { + id: 4, + title: translate('::ListForms.ListFormEdit.TabWidgets') || 'Widgets', + }, + { + id: 5, + title: translate('::ListForms.ListFormEdit.TabWorkflow') || 'Workflow', + }, + ...(values.todo + ? [ + { + id: 6, + title: translate('::ListForms.ListFormEdit.TabTodo') || 'Todo / Kanban', + }, + ] + : []), + ...(values.tree + ? [ + { + id: 7, + title: translate('::ListForms.ListFormEdit.TabTree') || 'Tree', + }, + ] + : []), + ...(values.gantt + ? [ + { + id: 8, + title: translate('::ListForms.ListFormEdit.TabGantt') || 'Gantt', + }, + ] + : []), + ...(values.scheduler + ? [ + { + id: 9, + title: translate('::ListForms.ListFormEdit.TabScheduler') || 'Scheduler', + }, + ] + : []), + { id: 10, title: translate('::App.Platform.Deploy') || 'Deploy' }, + ] - {/* ─── Step 2: Data Settings ───────────────────────────── */} - {currentStep === 1 && ( - { - setSelectCommandColumns([]) - setSelectedColumns(new Set()) - }} - onToggleColumn={toggleColumn} - onToggleAllColumns={(all) => toggleAllColumns(all, values.isTenant)} - onTenantChange={handleTenantChange} - translate={translate} - onBack={handleBack} - onNext={handleNext2} - /> - )} + const goToAdjacentStep = (direction: -1 | 1) => { + const currentIndex = activeSteps.findIndex((step) => step.id === currentStep) + const targetStep = activeSteps[currentIndex + direction] + if (targetStep) { + setCurrentStep(targetStep.id) + } + } - {/* ─── Step 3: List Form Fields ───────────────────────────── */} - {currentStep === 2 && ( - setCurrentStep(1)} - onNext={() => setCurrentStep(3)} - /> - )} + return ( + <> +
+ step.id === currentStep) + 1} + className="flex flex-row flex-wrap !justify-start gap-y-2 lg:flex-nowrap lg:!justify-between" + > + } + status="pending" + title={translate('::App.Listforms.WizardManager') || 'Wizard Manager'} + onStepChange={() => + navigate(ROUTES_ENUM.protected.saas.listFormManagement.wizardManager) + } + /> + {activeSteps.map((step) => ( + + ))} + +
- {/* ─── Step 4: Sub Forms ───────────────────────────── */} - {currentStep === 3 && ( - setCurrentStep(2)} - onNext={() => setCurrentStep(4)} - /> - )} + + = 2 ? undefined : 'sm'}> + {/* ─── Step 1: Basic Info ─────────────────────────────── */} + {currentStep === 0 && ( + { + formikRef.current?.setFieldValue('menuParentCode', '') + formikRef.current?.setFieldValue('menuParentShortName', '') + formikRef.current?.setFieldValue('menuParentIcon', '') + }} + onMenuCreated={handleMenuCreated} + onReloadMenu={getMenuList} + permissionGroupList={permissionGroupList} + isLoadingPermissionGroup={isLoadingPermissionGroup} + onNext={handleNext} + translate={translate} + /> + )} - {/* ─── Step 5: Widgets ───────────────────────────── */} - {currentStep === 4 && ( - setCurrentStep(3)} - onNext={() => setCurrentStep(5)} - /> - )} + {/* ─── Step 2: Data Settings ───────────────────────────── */} + {currentStep === 1 && ( + { + setSelectCommandColumns([]) + setSelectedColumns(new Set()) + }} + onToggleColumn={toggleColumn} + onToggleAllColumns={(all) => toggleAllColumns(all, values.isTenant)} + onTenantChange={handleTenantChange} + translate={translate} + onBack={handleBack} + onNext={handleNext2} + /> + )} - {/* ─── Step 6: Workflow ───────────────────────────── */} - {currentStep === 5 && ( - setCurrentStep(4)} - onNext={() => setCurrentStep(6)} - /> - )} + {/* ─── Step 3: List Form Fields ───────────────────────────── */} + {currentStep === 2 && ( + setCurrentStep(1)} + onNext={() => setCurrentStep(3)} + /> + )} - {/* ─── Step 7: Todo / Kanban ────────────────────── */} - {currentStep === 6 && ( - setCurrentStep(5)} - onNext={() => setCurrentStep(7)} - /> - )} + {/* ─── Step 4: Sub Forms ───────────────────────────── */} + {currentStep === 3 && ( + setCurrentStep(2)} + onNext={() => setCurrentStep(4)} + /> + )} - {/* ─── Step 8: Deploy ───────────────────────────── */} - {currentStep === 7 && ( - setCurrentStep(6)} - onSubmit={handleDeploy} - /> - )} - - - )} + {/* ─── Step 5: Widgets ───────────────────────────── */} + {currentStep === 4 && ( + setCurrentStep(3)} + onNext={() => setCurrentStep(5)} + /> + )} + + {/* ─── Step 6: Workflow ───────────────────────────── */} + {currentStep === 5 && ( + setCurrentStep(4)} + onNext={() => goToAdjacentStep(1)} + /> + )} + + {/* ─── Step 7: Todo / Kanban ────────────────────── */} + {currentStep === 6 && values.todo && ( + goToAdjacentStep(-1)} + onNext={() => goToAdjacentStep(1)} + /> + )} + + {/* ─── Step 8: Tree ─────────────────────────────── */} + {currentStep === 7 && values.tree && ( + goToAdjacentStep(-1)} + onNext={() => goToAdjacentStep(1)} + /> + )} + + {/* ─── Step 9: Gantt ────────────────────────────── */} + {currentStep === 8 && values.gantt && ( + goToAdjacentStep(-1)} + onNext={() => goToAdjacentStep(1)} + /> + )} + + {/* ─── Step 10: Scheduler ───────────────────────── */} + {currentStep === 9 && values.scheduler && ( + goToAdjacentStep(-1)} + onNext={() => goToAdjacentStep(1)} + /> + )} + + {/* ─── Step 11: Deploy ──────────────────────────── */} + {currentStep === 10 && ( + goToAdjacentStep(-1)} + onSubmit={handleDeploy} + /> + )} +
+ + + ) + }} ) diff --git a/ui/src/views/admin/listForm/wizard/WizardStep10.tsx b/ui/src/views/admin/listForm/wizard/WizardStep10.tsx new file mode 100644 index 00000000..a920ae62 --- /dev/null +++ b/ui/src/views/admin/listForm/wizard/WizardStep10.tsx @@ -0,0 +1,163 @@ +import { Button, Card, Checkbox, FormItem, Input, Select } from '@/components/ui' +import type { ListFormWizardDto } from '@/proxy/admin/wizard/models' +import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models' +import type { SelectBoxOption } from '@/types/shared' +import { Field, type FieldProps, useFormikContext } from 'formik' +import { useMemo } from 'react' +import { FaArrowLeft, FaArrowRight } from 'react-icons/fa' +import { firstDayOfWeekOptions, schedulerViewOptions } from '../edit/options' + +interface WizardStep10Props { + selectCommandColumns: DatabaseColumnDto[] + translate: (key: string) => string + onBack: () => void + onNext: () => void +} + +const WizardStep10 = ({ selectCommandColumns, translate, onBack, onNext }: WizardStep10Props) => { + const { values } = useFormikContext() + const fieldOptions = useMemo( + () => + selectCommandColumns.map((column) => ({ + value: column.columnName, + label: column.columnName, + })), + [selectCommandColumns], + ) + const option = values.schedulerOptionDto + const fieldMappings = [ + ['textExpr', '::ListForms.SchedulerOptions.TextExpr'], + ['startDateExpr', '::ListForms.SchedulerOptions.StartDateExpr'], + ['endDateExpr', '::ListForms.SchedulerOptions.EndDateExpr'], + ['allDayExpr', '::ListForms.SchedulerOptions.AllDayExpr'], + ['recurrenceRuleExpr', '::ListForms.SchedulerOptions.RecurrenceRuleExpr'], + ['recurrenceExceptionExpr', '::ListForms.SchedulerOptions.RecurrenceExceptionExpr'], + ] as const + const interactionFields = [ + ['showAllDayPanel', '::ListForms.SchedulerOptions.ShowAllDayPanel'], + ['crossScrollingEnabled', '::ListForms.SchedulerOptions.CrossScrollingEnabled'], + ['allowResizing', '::ListForms.SchedulerOptions.AllowResizing'], + ['allowDragging', '::ListForms.SchedulerOptions.AllowDragging'], + ['allowAdding', '::ListForms.SchedulerOptions.AllowAdding'], + ['allowEditing', '::ListForms.ListFormEdit.AllowEditing'], + ['allowDeleting', '::ListForms.SchedulerOptions.AllowDeleting'], + ] as const + + return ( +
+
+ + {fieldMappings.slice(0, 4).map(([name, translationKey]) => ( + + + {({ field, form }: FieldProps) => ( + viewOption.value === option.defaultView, + )} + onChange={(selected) => form.setFieldValue(field.name, selected?.value ?? 'week')} + /> + )} + + + + + {({ field, form }: FieldProps) => ( + fieldOption.value === option[name])} + onChange={(selected) => form.setFieldValue(field.name, selected?.value ?? '')} + /> + )} + + + ))} + + + + {interactionFields.map(([name, translationKey]) => ( + + + + ))} + +
+ +
+
+ + +
+
+
+ ) +} + +export default WizardStep10 diff --git a/ui/src/views/admin/listForm/wizard/WizardStep11.tsx b/ui/src/views/admin/listForm/wizard/WizardStep11.tsx new file mode 100644 index 00000000..bae813d2 --- /dev/null +++ b/ui/src/views/admin/listForm/wizard/WizardStep11.tsx @@ -0,0 +1,779 @@ +import { Button } from '@/components/ui' +import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models' +import React, { useState } from 'react' +import { + FaArrowLeft, + FaCheckCircle, + FaChevronDown, + FaChevronRight, + FaCircle, + FaExclamationCircle, + FaRocket, + FaSpinner, +} from 'react-icons/fa' +import { WizardGroup } from './WizardStep3' +import { dbSourceTypeOptions, selectCommandTypeOptions } from '../edit/options' +import { ListFormWizardDto } from '@/proxy/admin/wizard/models' +import { + ListFormWorkflowCriteriaDto, + SubFormDto, + WidgetEditDto, + WorkflowDto, +} from '@/proxy/form/models' +import { formatWorkflowApprovers } from '@/utils/workflow/workflowHelpers' + +// ─── Types ──────────────────────────────────────────────────────────────────── + +export interface WizardStep11Props { + values: ListFormWizardDto + wizardName: string + selectedColumns: Set + selectCommandColumns: DatabaseColumnDto[] + groups: WizardGroup[] + subForms: SubFormDto[] + widgets: WidgetEditDto[] + workflow: WorkflowDto + criteria: ListFormWorkflowCriteriaDto[] + translate: (key: string) => string + onBack: () => void + onSubmit: () => Promise +} + +type LogStatus = 'pending' | 'running' | 'success' | 'error' + +interface LogEntry { + id: number + label: string + status: LogStatus + detail?: string +} + +// ─── Deploy log steps ───────────────────────────────────────────────────────── + +function buildLogSteps( + values: ListFormWizardDto, + groups: WizardGroup[], + translate: (key: string, params?: Record) => string, +): Omit[] { + const totalFields = groups.reduce((acc, g) => acc + g.items.length, 0) + return [ + { id: 1, label: translate('::ListForms.Wizard.Step4.Log.ValidatingConfig') }, + { + id: 2, + label: translate('::ListForms.Wizard.Step4.Log.CreatingMenu', { 0: values.menuCode }), + detail: `Parent: ${values.menuParentCode}`, + }, + { + id: 3, + label: translate('::ListForms.Wizard.Step4.Log.SavingLanguageTexts'), + detail: `EN: ${values.languageTextMenuEn} / TR: ${values.languageTextMenuTr}`, + }, + { + id: 4, + label: translate('::ListForms.Wizard.Step4.Log.ConfiguringPermission', { + 0: values.permissionGroupName, + }), + }, + { + id: 5, + label: translate('::ListForms.Wizard.Step4.Log.ConnectingDataSource', { + 0: values.dataSourceCode, + }), + }, + { + id: 6, + label: translate('::ListForms.Wizard.Step4.Log.CreatingListForm', { 0: values.listFormCode }), + detail: `Key: ${values.keyFieldName}`, + }, + { + id: 7, + label: translate('::ListForms.Wizard.Step4.Log.SavingFormGroups', { + 0: groups.length, + 1: totalFields, + }), + }, + { id: 8, label: translate('::ListForms.Wizard.Step4.Log.Deploying') }, + { id: 9, label: translate('::ListForms.Wizard.Step4.Log.Completed') }, + ] +} + +// ─── Mini-components ────────────────────────────────────────────────────────── + +function LogIcon({ status }: { status: LogStatus }) { + if (status === 'running') return + if (status === 'success') return + if (status === 'error') return + return +} + +interface SectionProps { + title: string + badge?: string | number + children: React.ReactNode + defaultOpen?: boolean +} + +function Section({ title, badge, children, defaultOpen = true }: SectionProps) { + const [open, setOpen] = useState(defaultOpen) + return ( +
+ + {open &&
{children}
} +
+ ) +} + +function Row({ label, value }: { label: string; value?: string | number }) { + if (!value && value !== 0) return null + return ( +
+ {label} + + {value} + +
+ ) +} + +// ─── WizardStep11 ───────────────────────────────────────────────────────────── +const WizardStep11 = ({ + values, + wizardName, + selectedColumns, + selectCommandColumns, + groups, + subForms, + widgets, + workflow, + criteria, + translate, + onBack, + onSubmit, +}: WizardStep11Props) => { + const [logs, setLogs] = useState([]) + const [isDeploying, setIsDeploying] = useState(false) + const [isDone, setIsDone] = useState(false) + const [hasError, setHasError] = useState(false) + + const steps = buildLogSteps(values, groups, translate) + + const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)) + + const runDeploy = async () => { + if (isDeploying) return + setIsDeploying(true) + setHasError(false) + setIsDone(false) + + // Initialize all as pending + setLogs(steps.map((s) => ({ ...s, status: 'pending' }))) + + const setStatus = (id: number, status: LogStatus) => + setLogs((prev) => prev.map((l) => (l.id === id ? { ...l, status } : l))) + + // Steps 1-7: pre-deploy simulation (fast) + for (let i = 0; i < steps.length - 2; i++) { + const step = steps[i] + setStatus(step.id, 'running') + await sleep(300 + Math.random() * 200) + setStatus(step.id, 'success') + } + + // Step 8: actual API call + const deployStep = steps[steps.length - 2] + setStatus(deployStep.id, 'running') + try { + await onSubmit() + setStatus(deployStep.id, 'success') + await sleep(200) + // Step 9: done + const doneStep = steps[steps.length - 1] + setStatus(doneStep.id, 'running') + await sleep(300) + setStatus(doneStep.id, 'success') + setIsDone(true) + } catch (err: any) { + setStatus(deployStep.id, 'error') + setLogs((prev) => [ + ...prev, + { + id: 999, + label: `${translate('::ListForms.Wizard.Step4.Error')}: ${ + err?.message ?? translate('::App.Platform.Unknown') + }`, + status: 'error', + }, + ]) + setHasError(true) + } finally { + setIsDeploying(false) + } + } + + const totalFields = groups.reduce((acc, g) => acc + g.items.length, 0) + const editingFormFields = groups.flatMap((g) => + g.items + .filter((item) => item.includeInEditingForm && item.fieldName !== values.keyFieldName) + .map((item) => ({ ...item, groupCaption: g.caption })), + ) + const groupedFieldNames = new Set(groups.flatMap((g) => g.items.map((item) => item.fieldName))) + const ungroupedSelectedColumns = [...selectedColumns].filter((col) => !groupedFieldNames.has(col)) + const hasWorkflowFields = Boolean( + workflow.approvalUserFieldName || + workflow.approvalDateFieldName || + workflow.approvalStatusFieldName || + workflow.approvalDescriptionFieldName, + ) + const workflowItems = criteria.length > 0 ? criteria : (workflow.criteria ?? []) + + return ( +
+ {/* ── Left: Summary ──────────────────────────────────────────── */} +
+
+
+ + + + + + + + + +
+ +
+ + + + + + + + o.value === values.selectCommandType) + ?.label ?? String(values.selectCommandType) + })`} + /> + o.value === values.keyFieldDbSourceType) + ?.label ?? String(values.keyFieldDbSourceType) + })`} + /> +
+
+ +
+
+ {[ + { + label: translate('::ListForms.Wizard.Step4.SelectedColumns'), + value: selectedColumns.size, + className: 'text-indigo-600 dark:text-indigo-400', + }, + { + label: translate('::ListForms.Wizard.Step4.EditingForm') || 'Popup Form', + value: editingFormFields.length, + className: 'text-emerald-600 dark:text-emerald-400', + }, + { + label: translate('::ListForms.Wizard.Step4.FormGroups'), + value: groups.length, + className: 'text-gray-700 dark:text-gray-200', + }, + ].map((item) => ( +
+
+ {item.value} +
+
{item.label}
+
+ ))} +
+ +
+ {groups.map((g) => ( +
+
+ + {g.caption || `(${translate('::ListForms.Wizard.Step4.StatGroup')})`} + +
+ + {g.items.length} {translate('::ListForms.Wizard.Step4.StatField')} + + + {g.colCount} {translate('::App.Listform.ListformField.Column')} + +
+
+
+ {g.items.length === 0 ? ( + + {translate('::ListForms.Wizard.Step4.NoFields') || 'Alan yok'} + + ) : ( + g.items.map((item) => { + const meta = selectCommandColumns.find((c) => c.columnName === item.fieldName) + const isKeyField = item.fieldName === values.keyFieldName + const isPopupField = item.includeInEditingForm && !isKeyField + return ( +
+
+ + {item.fieldName} + + {meta?.dataType && ( + + {meta.dataType} + + )} +
+
+ + {translate('::ListForms.Wizard.Step4.SelectedColumns') || 'List'} + + {isPopupField && ( + + {translate('::ListForms.Wizard.Step4.EditingForm') || 'Popup Form'} + + )} + {isKeyField && ( + + {translate('::ListForms.Wizard.Step4.KeyField')} + + )} + + {item.editorType} + + + span-{item.colSpan} + {item.isRequired && *} + +
+
+ ) + }) + )} +
+
+ ))} + {ungroupedSelectedColumns.length > 0 && ( +
+
+ {translate('::ListForms.Wizard.Step4.UngroupedColumns') || 'Ungrouped columns'} +
+
+ {ungroupedSelectedColumns.map((col) => { + const meta = selectCommandColumns.find((c) => c.columnName === col) + return ( + + {col} + {meta?.dataType && ( + + {meta.dataType} + + )} + + ) + })} +
+
+ )} +
+
+ + {subForms.length > 0 && ( +
+
+ {subForms.map((subForm, index) => ( +
+ + + + + {(subForm.relation || []).length > 0 && ( +
+ Relations +
+ {subForm.relation.map((relation, relationIndex) => ( + + {relation.parentFieldName} : {relation.childFieldName} + + ))} +
+
+ )} +
+ ))} +
+
+ )} + + {widgets.length > 0 && ( +
+
+ {widgets.map((widget, index) => ( +
+ + + + + + + + + + +
+ ))} +
+
+ )} + + {(hasWorkflowFields || workflowItems.length > 0) && ( +
+
+
+ + + + + +
+ {workflowItems.length > 0 && ( +
+ {workflowItems.map((criteria, index) => ( +
+
+ {criteria.title || criteria.kind || `Criteria ${index + 1}`} +
+ {criteria.kind === 'Compare' && ( +
+ {criteria.compareColumn} {criteria.compareOperator}{' '} + {criteria.compareValue} +
+ )} + {(criteria.kind === 'Approval' || criteria.kind === 'Inform') && + criteria.approver && ( +
+ Approver: {formatWorkflowApprovers(criteria.approver)} +
+ )} +
+ ))} +
+ )} +
+
+ )} + + {values.todo && ( +
+
+ + + + + + + + + + + +
+
+ )} +
+ + {/* ── Right: Deploy ──────────────────────────────────────────── */} +
+ {/* Stats */} +
+ {[ + { label: translate('::ListForms.Wizard.Step4.StatGroup'), value: groups.length }, + { label: translate('::ListForms.Wizard.Step4.StatField'), value: totalFields }, + { + label: translate('::ListForms.Wizard.Step4.EditingForm') || 'Popup Form', + value: editingFormFields.length, + }, + { + label: translate('::App.Listform.ListformField.Column'), + value: selectedColumns.size, + }, + { + label: translate('::ListForms.ListFormEdit.SubForms') || 'Sub Forms', + value: subForms.length, + }, + { + label: translate('::ListForms.ListFormEdit.TabWidgets') || 'Widgets', + value: widgets.length, + }, + { + label: translate('::ListForms.ListFormEdit.TabWorkflow') || 'Workflow', + value: workflowItems.length, + }, + { + label: translate('::ListForms.ListFormEdit.TabTodo') || 'Todo', + value: values.todo ? 1 : 0, + }, + ].map((s) => ( +
+
+ {s.value} +
+
{s.label}
+
+ ))} +
+ + {/* Log panel — grows to fill remaining height */} +
+
+ + + {translate('::ListForms.Wizard.Step4.DeployLog') || 'Deploy Log'} + + {isDone && ( + + {translate('::ListForms.Wizard.Step4.Success')} + + )} + {hasError && ( + + {translate('::ListForms.Wizard.Step4.Error')} + + )} +
+ +
+ {logs.length === 0 ? ( +
+ + + {translate('::ListForms.Wizard.Step4.AllInfoReady')} +
+ {translate('::ListForms.Wizard.Step4.DeployStartHint')} +
+
+ ) : ( +
+ {logs.map((log) => ( +
+ + + +
+ + {log.label} + + {log.detail && ( +
{log.detail}
+ )} +
+
+ ))} + {isDone && ( +
+ 🎉 {translate('::ListForms.Wizard.Step4.DeploySuccess')} +
+ )} +
+ )} +
+
+
+ + {/* ── Fixed Footer ─────────────────────────────────────────────── */} +
+
+ +
+ +
+
+
+
+ ) +} + +export default WizardStep11 diff --git a/ui/src/views/admin/listForm/wizard/WizardStep2.tsx b/ui/src/views/admin/listForm/wizard/WizardStep2.tsx index 4584b543..fb0c7d5b 100644 --- a/ui/src/views/admin/listForm/wizard/WizardStep2.tsx +++ b/ui/src/views/admin/listForm/wizard/WizardStep2.tsx @@ -6,7 +6,12 @@ import { Field, FieldProps, FormikErrors, FormikTouched, useFormikContext } from import { useState } from 'react' import CreatableSelect from 'react-select/creatable' import { FaArrowLeft, FaArrowRight, FaPlus, FaTable } from 'react-icons/fa' -import { dbSourceTypeOptions, listFormDefaultLayoutOptions, selectCommandTypeOptions, sqlDataTypeToDbType } from '../edit/options' +import { + dbSourceTypeOptions, + listFormDefaultLayoutOptions, + selectCommandTypeOptions, + sqlDataTypeToDbType, +} from '../edit/options' import { ListFormWizardDto } from '@/proxy/admin/wizard/models' import SqlTableDesignerDialog from '@/views/developerKit/SqlTableDesignerDialog' @@ -265,44 +270,44 @@ const WizardStep2 = ({
({ label: c.columnName, value: c.columnName }))} - value={values.treeKeyExpr ? { label: values.treeKeyExpr, value: values.treeKeyExpr } : null} - onChange={(opt: any) => form.setFieldValue(field.name, opt?.value ?? '')} - /> - )} - - - - - {({ field, form }: FieldProps) => ( - ({ label: c.columnName, value: c.columnName }))} - value={(values as any)[name] ? { label: (values as any)[name], value: (values as any)[name] } : null} - onChange={(opt: any) => form.setFieldValue(field.name, opt?.value ?? '')} - /> - )} - - - ))} - - - -
- )} - - {/* ── Scheduler options (full-width, shown when defaultLayout = 'scheduler') ─── */} - {values.defaultLayout === 'scheduler' && ( -
-
- {translate('::ListForms.ListFormEdit.DetailsLayoutDto.SchedulerLayout') || 'Scheduler Ayarları'} -
- {[ - { name: 'schedulerTextExpr', label: translate('::ListForms.SchedulerOptions.TextExpr') }, - { name: 'schedulerStartDateExpr', label: translate('::ListForms.SchedulerOptions.StartDateExpr') }, - { name: 'schedulerEndDateExpr', label: translate('::ListForms.SchedulerOptions.EndDateExpr') }, - ].map(({ name, label }) => ( - - - {({ field, form }: FieldProps) => ( - option.value === values[mapping.name])} + value={fieldOptions.find( + (option) => option.value === values.todoOptionDto[mapping.name], + )} onChange={(option) => { form.setFieldValue(field.name, option?.value ?? '') setValidationError('') @@ -131,13 +121,13 @@ const WizardStep7 = ({
- + {({ field }: FieldProps) => ( +interface WizardStep8Props { selectCommandColumns: DatabaseColumnDto[] - groups: WizardGroup[] - subForms: SubFormDto[] - widgets: WidgetEditDto[] - workflow: WorkflowDto - criteria: ListFormWorkflowCriteriaDto[] translate: (key: string) => string onBack: () => void - onSubmit: () => Promise + onNext: () => void } -type LogStatus = 'pending' | 'running' | 'success' | 'error' +const WizardStep8 = ({ selectCommandColumns, translate, onBack, onNext }: WizardStep8Props) => { + const { values } = useFormikContext() + const fieldOptions = useMemo( + () => + selectCommandColumns.map((column) => ({ + value: column.columnName, + label: column.columnName, + })), + [selectCommandColumns], + ) -interface LogEntry { - id: number - label: string - status: LogStatus - detail?: string -} - -// ─── Deploy log steps ───────────────────────────────────────────────────────── - -function buildLogSteps( - values: ListFormWizardDto, - groups: WizardGroup[], - translate: (key: string, params?: Record) => string, -): Omit[] { - const totalFields = groups.reduce((acc, g) => acc + g.items.length, 0) - return [ - { id: 1, label: translate('::ListForms.Wizard.Step4.Log.ValidatingConfig') }, + const selectFields = [ { - id: 2, - label: translate('::ListForms.Wizard.Step4.Log.CreatingMenu', { 0: values.menuCode }), - detail: `Parent: ${values.menuParentCode}`, + name: 'treeOptionDto.keyExpr', + value: values.treeOptionDto.keyExpr, + label: translate('::App.Listform.ListformField.KeyFieldName'), }, { - id: 3, - label: translate('::ListForms.Wizard.Step4.Log.SavingLanguageTexts'), - detail: `EN: ${values.languageTextMenuEn} / TR: ${values.languageTextMenuTr}`, + name: 'treeOptionDto.parentIdExpr', + value: values.treeOptionDto.parentIdExpr, + label: translate('::ListForms.ListFormEdit.ParentIdExpr'), }, - { - id: 4, - label: translate('::ListForms.Wizard.Step4.Log.ConfiguringPermission', { - 0: values.permissionGroupName, - }), - }, - { - id: 5, - label: translate('::ListForms.Wizard.Step4.Log.ConnectingDataSource', { - 0: values.dataSourceCode, - }), - }, - { - id: 6, - label: translate('::ListForms.Wizard.Step4.Log.CreatingListForm', { 0: values.listFormCode }), - detail: `Key: ${values.keyFieldName}`, - }, - { - id: 7, - label: translate('::ListForms.Wizard.Step4.Log.SavingFormGroups', { - 0: groups.length, - 1: totalFields, - }), - }, - { id: 8, label: translate('::ListForms.Wizard.Step4.Log.Deploying') }, - { id: 9, label: translate('::ListForms.Wizard.Step4.Log.Completed') }, ] -} - -// ─── Mini-components ────────────────────────────────────────────────────────── - -function LogIcon({ status }: { status: LogStatus }) { - if (status === 'running') return - if (status === 'success') return - if (status === 'error') return - return -} - -interface SectionProps { - title: string - badge?: string | number - children: React.ReactNode - defaultOpen?: boolean -} - -function Section({ title, badge, children, defaultOpen = true }: SectionProps) { - const [open, setOpen] = useState(defaultOpen) - return ( -
- - {open &&
{children}
} -
- ) -} - -function Row({ label, value }: { label: string; value?: string | number }) { - if (!value && value !== 0) return null - return ( -
- {label} - - {value} - -
- ) -} - -// ─── WizardStep8 ────────────────────────────────────────────────────────────── -const WizardStep8 = ({ - values, - wizardName, - selectedColumns, - selectCommandColumns, - groups, - subForms, - widgets, - workflow, - criteria, - translate, - onBack, - onSubmit, -}: WizardStep8Props) => { - const [logs, setLogs] = useState([]) - const [isDeploying, setIsDeploying] = useState(false) - const [isDone, setIsDone] = useState(false) - const [hasError, setHasError] = useState(false) - - const steps = buildLogSteps(values, groups, translate) - - const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)) - - const runDeploy = async () => { - if (isDeploying) return - setIsDeploying(true) - setHasError(false) - setIsDone(false) - - // Initialize all as pending - setLogs(steps.map((s) => ({ ...s, status: 'pending' }))) - - const setStatus = (id: number, status: LogStatus) => - setLogs((prev) => prev.map((l) => (l.id === id ? { ...l, status } : l))) - - // Steps 1-7: pre-deploy simulation (fast) - for (let i = 0; i < steps.length - 2; i++) { - const step = steps[i] - setStatus(step.id, 'running') - await sleep(300 + Math.random() * 200) - setStatus(step.id, 'success') - } - - // Step 8: actual API call - const deployStep = steps[steps.length - 2] - setStatus(deployStep.id, 'running') - try { - await onSubmit() - setStatus(deployStep.id, 'success') - await sleep(200) - // Step 9: done - const doneStep = steps[steps.length - 1] - setStatus(doneStep.id, 'running') - await sleep(300) - setStatus(doneStep.id, 'success') - setIsDone(true) - } catch (err: any) { - setStatus(deployStep.id, 'error') - setLogs((prev) => [ - ...prev, - { - id: 999, - label: `${translate('::ListForms.Wizard.Step4.Error')}: ${ - err?.message ?? translate('::App.Platform.Unknown') - }`, - status: 'error', - }, - ]) - setHasError(true) - } finally { - setIsDeploying(false) - } - } - - const totalFields = groups.reduce((acc, g) => acc + g.items.length, 0) - const editingFormFields = groups.flatMap((g) => - g.items - .filter((item) => item.includeInEditingForm && item.fieldName !== values.keyFieldName) - .map((item) => ({ ...item, groupCaption: g.caption })), - ) - const groupedFieldNames = new Set(groups.flatMap((g) => g.items.map((item) => item.fieldName))) - const ungroupedSelectedColumns = [...selectedColumns].filter((col) => !groupedFieldNames.has(col)) - const hasWorkflowFields = Boolean( - workflow.approvalUserFieldName || - workflow.approvalDateFieldName || - workflow.approvalStatusFieldName || - workflow.approvalDescriptionFieldName, - ) - const workflowItems = criteria.length > 0 ? criteria : (workflow.criteria ?? []) return ( -
- {/* ── Left: Summary ──────────────────────────────────────────── */} -
-
-
- - - - - - - - - -
- -
- - - - - - - - o.value === values.selectCommandType) - ?.label ?? String(values.selectCommandType) - })`} - /> - o.value === values.keyFieldDbSourceType) - ?.label ?? String(values.keyFieldDbSourceType) - })`} - /> -
-
- -
-
- {[ - { - label: translate('::ListForms.Wizard.Step4.SelectedColumns'), - value: selectedColumns.size, - className: 'text-indigo-600 dark:text-indigo-400', - }, - { - label: translate('::ListForms.Wizard.Step4.EditingForm') || 'Popup Form', - value: editingFormFields.length, - className: 'text-emerald-600 dark:text-emerald-400', - }, - { - label: translate('::ListForms.Wizard.Step4.FormGroups'), - value: groups.length, - className: 'text-gray-700 dark:text-gray-200', - }, - ].map((item) => ( -
-
- {item.value} -
-
{item.label}
-
- ))} -
- -
- {groups.map((g) => ( -
-
- - {g.caption || `(${translate('::ListForms.Wizard.Step4.StatGroup')})`} - -
- - {g.items.length} {translate('::ListForms.Wizard.Step4.StatField')} - - - {g.colCount} {translate('::App.Listform.ListformField.Column')} - -
-
-
- {g.items.length === 0 ? ( - - {translate('::ListForms.Wizard.Step4.NoFields') || 'Alan yok'} - - ) : ( - g.items.map((item) => { - const meta = selectCommandColumns.find((c) => c.columnName === item.fieldName) - const isKeyField = item.fieldName === values.keyFieldName - const isPopupField = item.includeInEditingForm && !isKeyField - return ( -
-
- - {item.fieldName} - - {meta?.dataType && ( - - {meta.dataType} - - )} -
-
- - {translate('::ListForms.Wizard.Step4.SelectedColumns') || 'List'} - - {isPopupField && ( - - {translate('::ListForms.Wizard.Step4.EditingForm') || 'Popup Form'} - - )} - {isKeyField && ( - - {translate('::ListForms.Wizard.Step4.KeyField')} - - )} - - {item.editorType} - - - span-{item.colSpan} - {item.isRequired && *} - -
-
- ) - }) - )} -
-
- ))} - {ungroupedSelectedColumns.length > 0 && ( -
-
- {translate('::ListForms.Wizard.Step4.UngroupedColumns') || 'Ungrouped columns'} -
-
- {ungroupedSelectedColumns.map((col) => { - const meta = selectCommandColumns.find((c) => c.columnName === col) - return ( - - {col} - {meta?.dataType && ( - - {meta.dataType} - - )} - - ) - })} -
-
- )} -
-
- - {subForms.length > 0 && ( -
-
- {subForms.map((subForm, index) => ( -
- - - - - {(subForm.relation || []).length > 0 && ( -
- Relations -
- {subForm.relation.map((relation, relationIndex) => ( - - {relation.parentFieldName} : {relation.childFieldName} - - ))} -
-
- )} -
- ))} -
-
- )} - - {widgets.length > 0 && ( -
-
- {widgets.map((widget, index) => ( -
- - - - - - - - - - -
- ))} -
-
- )} - - {(hasWorkflowFields || workflowItems.length > 0) && ( -
-
-
- - - - - +
+ {selectFields.map((item) => ( + + + {({ field, form }: FieldProps) => ( + fieldOption.value === option[name])} + onChange={(selected) => form.setFieldValue(field.name, selected?.value ?? '')} + /> + )} + + + ))} + + + + + + + + + {({ field, form }: FieldProps) => ( +