From 73cb479e50881a958b7e917e896a2f07c1982a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Sat, 23 May 2026 16:41:52 +0300 Subject: [PATCH] =?UTF-8?q?LisformWorkflow=20=C3=A7al=C4=B1=C5=9Fmas=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ListForms/GridOptionsDto/WorkflowDto.cs | 7 +- ...CreateUpdateListFormWorkflowCriteriaDto.cs | 2 +- .../Workflow/IListFormWorkflowAppService.cs | 2 +- .../Workflow/ListFormWorkflowCriteriaDto.cs | 2 +- .../ListForms/ListFormWorkflowAppService.cs | 75 ++- .../Seeds/LanguagesData.json | 72 +++ .../Tenant/ListForm/ListFormWorkflow.cs | 4 +- .../EntityFrameworkCore/PlatformDbContext.cs | 1 + ....cs => 20260523104659_Initial.Designer.cs} | 7 +- ...9_Initial.cs => 20260523104659_Initial.cs} | 2 +- .../PlatformDbContextModelSnapshot.cs | 5 +- ui/src/proxy/admin/list-form/options.ts | 1 + ui/src/proxy/form/models.ts | 7 + ui/src/utils/workflow/workflowConstants.ts | 5 - ui/src/utils/workflow/workflowHelpers.ts | 12 +- ui/src/views/admin/listForm/edit/FormEdit.tsx | 111 +++- .../admin/listForm/edit/FormTabWorkflow.tsx | 238 ++++++-- .../admin/listForm/workflow/CriteriaTable.tsx | 484 ----------------- .../listForm/workflow/DashboardShell.tsx | 117 ---- .../{FlowCanvas.tsx => WorkflowCanvas.tsx} | 7 +- .../listForm/workflow/WorkflowCriteria.tsx | 512 ++++++++++++++++++ .../listForm/workflow/WorkflowDesigner.tsx | 138 +++-- 22 files changed, 1058 insertions(+), 753 deletions(-) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20260522200739_Initial.Designer.cs => 20260523104659_Initial.Designer.cs} (99%) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20260522200739_Initial.cs => 20260523104659_Initial.cs} (99%) delete mode 100644 ui/src/views/admin/listForm/workflow/CriteriaTable.tsx delete mode 100644 ui/src/views/admin/listForm/workflow/DashboardShell.tsx rename ui/src/views/admin/listForm/workflow/{FlowCanvas.tsx => WorkflowCanvas.tsx} (99%) create mode 100644 ui/src/views/admin/listForm/workflow/WorkflowCriteria.tsx diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/WorkflowDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/WorkflowDto.cs index 2c67380..740aedc 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/WorkflowDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/WorkflowDto.cs @@ -1,9 +1,8 @@ -using System; - -namespace Sozsoft.Platform.ListForms; +namespace Sozsoft.Platform.ListForms; public class WorkflowDto { public string ApprovalFieldName { get; set; } - public DateTime ApprovalDateFieldName { get; set; } + public string ApprovalDateFieldName { get; set; } + public string ApprovalStatusFieldName { get; set; } } diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/CreateUpdateListFormWorkflowCriteriaDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/CreateUpdateListFormWorkflowCriteriaDto.cs index 3cb3f7c..cff8e97 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/CreateUpdateListFormWorkflowCriteriaDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/CreateUpdateListFormWorkflowCriteriaDto.cs @@ -5,7 +5,7 @@ namespace Sozsoft.Platform.ListForms.Workflow; public class CreateUpdateListFormWorkflowCriteriaDto { - public Guid? Id { get; set; } + public string Id { get; set; } public string ListFormCode { get; set; } public string Kind { get; set; } public string Title { get; set; } diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/IListFormWorkflowAppService.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/IListFormWorkflowAppService.cs index 86e0c5f..16a0b04 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/IListFormWorkflowAppService.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/IListFormWorkflowAppService.cs @@ -8,7 +8,7 @@ public interface IListFormWorkflowAppService : IApplicationService { Task GetStateAsync(string listFormCode = null); Task SaveCriteriaAsync(CreateUpdateListFormWorkflowCriteriaDto input); - Task DeleteCriteriaAsync(Guid id); + Task DeleteCriteriaAsync(string id); Task ResetDemoAsync(string listFormCode = null); } diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/ListFormWorkflowCriteriaDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/ListFormWorkflowCriteriaDto.cs index f479070..a9e791b 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/ListFormWorkflowCriteriaDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/Workflow/ListFormWorkflowCriteriaDto.cs @@ -4,7 +4,7 @@ using Volo.Abp.Application.Dtos; namespace Sozsoft.Platform.ListForms.Workflow; -public class ListFormWorkflowCriteriaDto : AuditedEntityDto +public class ListFormWorkflowCriteriaDto : AuditedEntityDto { public string ListFormCode { get; set; } public string Kind { get; set; } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs index 2d912d0..7dd49ca 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs @@ -16,10 +16,12 @@ namespace Sozsoft.Platform.ListForms.Workflow; public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowAppService { private const string DefaultListFormCode = "workflow"; + private const string CriteriaIdPrefix = "N"; + private const int CriteriaIdPadding = 3; - private readonly IRepository criteriaRepository; + private readonly IRepository criteriaRepository; - public ListFormWorkflowAppService(IRepository criteriaRepository) + public ListFormWorkflowAppService(IRepository criteriaRepository) { this.criteriaRepository = criteriaRepository; } @@ -43,10 +45,10 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA public async Task SaveCriteriaAsync(CreateUpdateListFormWorkflowCriteriaDto input) { var code = NormalizeListFormCode(input.ListFormCode); - var isNew = !input.Id.HasValue || input.Id.Value == Guid.Empty; + var isNew = input.Id.IsNullOrWhiteSpace(); var criteria = isNew - ? new ListFormWorkflow(GuidGenerator.Create()) - : await criteriaRepository.GetAsync(input.Id.Value); + ? new ListFormWorkflow(await GenerateNextCriteriaIdAsync()) + : await criteriaRepository.GetAsync(input.Id); if (!isNew && criteria.ListFormCode != code) { @@ -89,7 +91,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA } [HttpDelete("criteria/{id}")] - public async Task DeleteCriteriaAsync(Guid id) + public async Task DeleteCriteriaAsync(string id) { var criteria = await criteriaRepository.GetAsync(id); await criteriaRepository.DeleteAsync(criteria, autoSave: true); @@ -97,7 +99,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA var remaining = await criteriaRepository.GetListAsync(x => x.ListFormCode == criteria.ListFormCode); foreach (var item in remaining) { - var changed = ClearDeletedTarget(item, id.ToString()); + var changed = ClearDeletedTarget(item, id); if (changed) { await criteriaRepository.UpdateAsync(item, autoSave: true); @@ -117,30 +119,30 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA var start = await CreateCriteriaAsync(code, "Start", "İş Akışı Başlat", 80, 150); var compare = await CreateCriteriaAsync(code, "Compare", "Tutar kontrolü", 330, 130); - var approval = await CreateCriteriaAsync(code, "Approval", "Yönetici Onayı", 590, 60, "ayse.yilmaz"); - var inform = await CreateCriteriaAsync(code, "Inform", "Muhasebe Bilgilendirme", 590, 230, "muhasebe"); + var approval = await CreateCriteriaAsync(code, "Approval", "Yönetici Onayı", 590, 60, PlatformConsts.AbpIdentity.User.AdminEmailDefaultValue); + var inform = await CreateCriteriaAsync(code, "Inform", "Muhasebe Bilgilendirme", 590, 230, PlatformConsts.AbpIdentity.User.AdminEmailDefaultValue); var end = await CreateCriteriaAsync(code, "End", "Akışı Bitir", 850, 150); - start.NextOnStart = compare.Id.ToString(); - compare.NextOnTrue = approval.Id.ToString(); - compare.NextOnFalse = inform.Id.ToString(); + start.NextOnStart = compare.Id; + compare.NextOnTrue = approval.Id; + compare.NextOnFalse = inform.Id; compare.CompareOutcomesJson = SerializeCompareOutcomes([ new CompareOutcomeDto { Label = "Onay gerekir", - TargetId = approval.Id.ToString(), + TargetId = approval.Id, Conditions = [new WorkflowConditionDto { CompareColumn = "Tutar", CompareOperator = ">", CompareValue = 5000 }] }, new CompareOutcomeDto { Label = "Bilgilendir", - TargetId = inform.Id.ToString(), + TargetId = inform.Id, Conditions = [new WorkflowConditionDto { CompareColumn = "Tutar", CompareOperator = "<=", CompareValue = 5000 }] } ]); - approval.NextOnApprove = inform.Id.ToString(); - approval.NextOnReject = end.Id.ToString(); - inform.NextOnStart = end.Id.ToString(); + approval.NextOnApprove = inform.Id; + approval.NextOnReject = end.Id; + inform.NextOnStart = end.Id; await criteriaRepository.UpdateAsync(start, autoSave: true); await criteriaRepository.UpdateAsync(compare, autoSave: true); @@ -158,7 +160,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA int positionY, string approver = "") { - var criteria = new ListFormWorkflow(GuidGenerator.Create()) + var criteria = new ListFormWorkflow(await GenerateNextCriteriaIdAsync()) { ListFormCode = listFormCode, Kind = kind, @@ -181,6 +183,43 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA return criteria; } + private async Task GenerateNextCriteriaIdAsync() + { + var criteria = await criteriaRepository.GetListAsync(); + var maxNumber = criteria + .Select(x => TryParseCriteriaIdNumber(x.Id)) + .DefaultIfEmpty(0) + .Max(); + + var nextNumber = maxNumber + 1; + var nextId = FormatCriteriaId(nextNumber); + var existingIds = criteria.Select(x => x.Id).ToHashSet(); + + while (existingIds.Contains(nextId)) + { + nextNumber++; + nextId = FormatCriteriaId(nextNumber); + } + + return nextId; + } + + private static int TryParseCriteriaIdNumber(string id) + { + if (id.IsNullOrWhiteSpace() || + !id.StartsWith(CriteriaIdPrefix, StringComparison.OrdinalIgnoreCase)) + { + return 0; + } + + return int.TryParse(id[CriteriaIdPrefix.Length..], out var number) ? number : 0; + } + + private static string FormatCriteriaId(int number) + { + return $"{CriteriaIdPrefix}{number.ToString().PadLeft(CriteriaIdPadding, '0')}"; + } + private static bool ClearDeletedTarget(ListFormWorkflow criteria, string deletedId) { var changed = false; diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index 7f815b5..a0fb216 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -18673,6 +18673,78 @@ "key": "SuccessfullySaved", "en": "Successfully Saved", "tr": "Başarıyla Kaydedildi" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.Criteria", + "en": "Criteria", + "tr": "Kriterler" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaStart", + "en": "Start", + "tr": "Başlat" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaCompare", + "en": "Compare", + "tr": "Karşılaştır" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaApproval", + "en": "Approval", + "tr": "Onaylanacak Kişi" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaInform", + "en": "Information", + "tr": "Bilgilendirilecek Kişi" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaEnd", + "en": "Finish", + "tr": "Akışı Bitir" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaTitleRule", + "en": "Title / Rule", + "tr": "Başlık / Kural" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.CriteriaConnections", + "en": "Connections", + "tr": "Bağlantılar" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.WorkflowNoCriteria", + "en": "No criteria defined for the selected workflow.", + "tr": "Seçili iş akışı için açıklama kaydı yok." + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.ApprovalFieldName", + "en": "Approval Field Name", + "tr": "Onay Alanı Adı" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.ApprovalDateFieldName", + "en": "Approval Date Field Name", + "tr": "Onay Tarihi Alanı Adı" + }, + { + "resourceName": "Platform", + "key": "ListForms.ListFormEdit.Workflow.ApprovalStatusFieldName", + "en": "Approval Status Field Name", + "tr": "Onay Durumu Alanı Adı" } ] } \ No newline at end of file diff --git a/api/src/Sozsoft.Platform.Domain/Entities/Tenant/ListForm/ListFormWorkflow.cs b/api/src/Sozsoft.Platform.Domain/Entities/Tenant/ListForm/ListFormWorkflow.cs index 338fe6e..11ae3c3 100644 --- a/api/src/Sozsoft.Platform.Domain/Entities/Tenant/ListForm/ListFormWorkflow.cs +++ b/api/src/Sozsoft.Platform.Domain/Entities/Tenant/ListForm/ListFormWorkflow.cs @@ -3,13 +3,13 @@ using Volo.Abp.Domain.Entities; namespace Sozsoft.Platform.Entities; -public class ListFormWorkflow : Entity +public class ListFormWorkflow : Entity { protected ListFormWorkflow() { } - public ListFormWorkflow(Guid id) : base(id) + public ListFormWorkflow(string id) : base(id) { } diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 6f6efd6..3134044 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -487,6 +487,7 @@ public class PlatformDbContext : b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ListFormWorkflow)), Prefix.DbSchema); b.ConfigureByConvention(); + b.Property(x => x.Id).HasMaxLength(50); b.Property(x => x.ListFormCode).IsRequired().HasMaxLength(64); b.Property(x => x.Kind).IsRequired().HasMaxLength(50); b.Property(x => x.Title).IsRequired().HasMaxLength(250); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260522200739_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260523104659_Initial.Designer.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260522200739_Initial.Designer.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260523104659_Initial.Designer.cs index ef48921..896d038 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260522200739_Initial.Designer.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260523104659_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Sozsoft.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20260522200739_Initial")] + [Migration("20260523104659_Initial")] partial class Initial { /// @@ -3414,8 +3414,9 @@ namespace Sozsoft.Platform.Migrations modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b => { - b.Property("Id") - .HasColumnType("uniqueidentifier"); + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); b.Property("Approver") .IsRequired() diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260522200739_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260523104659_Initial.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260522200739_Initial.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260523104659_Initial.cs index 71b932e..7751740 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260522200739_Initial.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260523104659_Initial.cs @@ -1393,7 +1393,7 @@ namespace Sozsoft.Platform.Migrations name: "Sas_H_ListFormWorkflow", columns: table => new { - Id = table.Column(type: "uniqueidentifier", nullable: false), + Id = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), ListFormCode = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), Kind = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), Title = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index a86f3a8..646dab4 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -3411,8 +3411,9 @@ namespace Sozsoft.Platform.Migrations modelBuilder.Entity("Sozsoft.Platform.Entities.ListFormWorkflow", b => { - b.Property("Id") - .HasColumnType("uniqueidentifier"); + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); b.Property("Approver") .IsRequired() diff --git a/ui/src/proxy/admin/list-form/options.ts b/ui/src/proxy/admin/list-form/options.ts index 5afcf3e..ab7e3e4 100644 --- a/ui/src/proxy/admin/list-form/options.ts +++ b/ui/src/proxy/admin/list-form/options.ts @@ -48,6 +48,7 @@ export const ListFormEditTabs = { StateForm: 'state', SubForm: 'subForm', Widget: 'widget', + Workflow: 'workflow', Fields: 'fields', Customization: 'customization', ExtraFilter: 'extraFilter', diff --git a/ui/src/proxy/form/models.ts b/ui/src/proxy/form/models.ts index 01bcb27..99816b8 100644 --- a/ui/src/proxy/form/models.ts +++ b/ui/src/proxy/form/models.ts @@ -663,6 +663,7 @@ export interface GridOptionsEditDto extends GridOptionsDto, Record formFieldsDefaultValueDto: FieldsDefaultValueDto[] widgetsJson?: string widgetsDto: WidgetEditDto[] + workflowDto: WorkflowDto extraFilterEditDto: ExtraFilterEditDto[] } @@ -905,6 +906,12 @@ export interface WidgetEditDto { isActive: boolean } +export interface WorkflowDto { + approvalFieldName: string + approvalDateFieldName: string + approvalStatusFieldName: string +} + export interface LayoutDto { grid: boolean pivot: boolean diff --git a/ui/src/utils/workflow/workflowConstants.ts b/ui/src/utils/workflow/workflowConstants.ts index 5dc25ab..12a6040 100644 --- a/ui/src/utils/workflow/workflowConstants.ts +++ b/ui/src/utils/workflow/workflowConstants.ts @@ -15,11 +15,6 @@ export const operatorOptions = [">", ">=", "<", "<=", "=", "!="].map( }), ); -export const columnOptions = ["Tutar", "Id"].map((value) => ({ - value, - label: value, -})); - export const kindIcon: Record = { Start: FiPlay as any, Compare: FiGitBranch as any, diff --git a/ui/src/utils/workflow/workflowHelpers.ts b/ui/src/utils/workflow/workflowHelpers.ts index 25a6536..fecece6 100644 --- a/ui/src/utils/workflow/workflowHelpers.ts +++ b/ui/src/utils/workflow/workflowHelpers.ts @@ -321,7 +321,7 @@ export function emptyCriteria(kind = 'Compare', listFormCode = ''): WorkflowCrit nextOnApprove: '', nextOnReject: '', compareOutcomes: - kind === 'Compare' ? [emptyCompareOutcome('Durum 1'), emptyCompareOutcome('Durum 2')] : [], + kind === 'Compare' ? [emptyCompareOutcome1('>5000'), emptyCompareOutcome2('<=5000')] : [], positionX: 32, positionY: 150, } @@ -375,7 +375,7 @@ export function defaultTitle(kind: string) { ) } -export function emptyCompareOutcome(label = 'Durum'): CompareOutcomeDto { +export function emptyCompareOutcome1(label = 'Durum'): CompareOutcomeDto { return { label, targetId: '', @@ -383,6 +383,14 @@ export function emptyCompareOutcome(label = 'Durum'): CompareOutcomeDto { } } +export function emptyCompareOutcome2(label = 'Durum'): CompareOutcomeDto { + return { + label, + targetId: '', + conditions: [{ compareColumn: 'Tutar', compareOperator: '<=', compareValue: 5000 }], + } +} + export function toCompareOutcomeForm( outcome: Partial & Partial & { diff --git a/ui/src/views/admin/listForm/edit/FormEdit.tsx b/ui/src/views/admin/listForm/edit/FormEdit.tsx index 8bff8f9..4d5026b 100644 --- a/ui/src/views/admin/listForm/edit/FormEdit.tsx +++ b/ui/src/views/admin/listForm/edit/FormEdit.tsx @@ -28,8 +28,11 @@ import FormFields from './form-fields/FormFields' import { putListForms } from '@/services/admin/list-form.service' import { getRoles, getUsers } from '@/services/identity.service' import { GridOptionsEditDto, ListFormCustomizationDto } from '@/proxy/form/models' +import { SelectCommandTypeEnum } from '@/proxy/form/models' import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models' import { getListFormCustomizations } from '@/services/admin/list-form-customization.service' +import { sqlObjectManagerService } from '@/services/sql-query-manager.service' +import type { DatabaseColumnDto, SqlObjectExplorerDto } from '@/proxy/sql-query-manager/models' import { Container } from '@/components/shared' import { ROUTES_ENUM } from '@/routes/route.constant' import FormTabWidgets from './FormTabWidgets' @@ -71,6 +74,8 @@ const FormEdit = () => { const [langOptions, setLangOptions] = useState([]) const [roleList, setRoleList] = useState([]) const [userList, setUserList] = useState([]) + const [workflowColumns, setWorkflowColumns] = useState([]) + const [isLoadingWorkflowColumns, setIsLoadingWorkflowColumns] = useState(false) const languages: LanguageInfo[] | undefined = useStoreState( (state) => state.abpConfig.config?.localization.languages, @@ -141,6 +146,51 @@ const FormEdit = () => { refreshData() }, [listFormCode]) + useEffect(() => { + const loadWorkflowColumns = async () => { + const dataSourceCode = listFormValues?.dataSourceCode + const selectCommand = listFormValues?.selectCommand + + if (!dataSourceCode || !selectCommand) { + setWorkflowColumns([]) + return + } + + setIsLoadingWorkflowColumns(true) + try { + const objectsResponse = await sqlObjectManagerService.getAllObjects(dataSourceCode) + const objects = objectsResponse.data + const objectInfo = findSelectCommandObject( + objects, + selectCommand, + listFormValues.selectCommandType, + ) + + if (!objectInfo) { + setWorkflowColumns([]) + return + } + + const columnsResponse = await sqlObjectManagerService.getTableColumns( + dataSourceCode, + objectInfo.schemaName, + objectInfo.objectName, + ) + setWorkflowColumns(columnsResponse.data ?? []) + } catch { + setWorkflowColumns([]) + } finally { + setIsLoadingWorkflowColumns(false) + } + } + + loadWorkflowColumns() + }, [ + listFormValues?.dataSourceCode, + listFormValues?.selectCommand, + listFormValues?.selectCommandType, + ]) + const onSubmit = async ( editType: string, values: GridOptionsEditDto, @@ -189,9 +239,12 @@ const FormEdit = () => { {/* SAĞ TARAF */} {listFormValues.isTenant && ( - - + )} @@ -392,7 +445,13 @@ const FormEdit = () => { - + { ) } +function findSelectCommandObject( + objects: SqlObjectExplorerDto | undefined, + selectCommand: string, + selectCommandType?: SelectCommandTypeEnum, +) { + if (!objects || !selectCommand || selectCommandType === SelectCommandTypeEnum.Query) { + return null + } + + if (selectCommandType === SelectCommandTypeEnum.Table) { + const table = objects.tables.find((item) => item.tableName === selectCommand) + return table ? { schemaName: table.schemaName, objectName: table.tableName } : null + } + + if (selectCommandType === SelectCommandTypeEnum.View) { + const view = objects.views.find((item) => item.objectName === selectCommand) + return view ? { schemaName: view.schemaName, objectName: view.objectName } : null + } + + if (selectCommandType === SelectCommandTypeEnum.TableValuedFunction) { + const fn = objects.functions.find((item) => item.objectName === selectCommand) + return fn ? { schemaName: fn.schemaName, objectName: fn.objectName } : null + } + + if (selectCommandType === SelectCommandTypeEnum.StoredProcedure) { + const sp = objects.storedProcedures.find((item) => item.objectName === selectCommand) + return sp ? { schemaName: sp.schemaName, objectName: sp.objectName } : null + } + + const table = objects.tables.find((item) => item.tableName === selectCommand) + if (table) return { schemaName: table.schemaName, objectName: table.tableName } + + const view = objects.views.find((item) => item.objectName === selectCommand) + if (view) return { schemaName: view.schemaName, objectName: view.objectName } + + const fn = objects.functions.find((item) => item.objectName === selectCommand) + if (fn) return { schemaName: fn.schemaName, objectName: fn.objectName } + + const sp = objects.storedProcedures.find((item) => item.objectName === selectCommand) + if (sp) return { schemaName: sp.schemaName, objectName: sp.objectName } + + return null +} + export default FormEdit diff --git a/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx b/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx index c53aee6..3fb31a9 100644 --- a/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx +++ b/ui/src/views/admin/listForm/edit/FormTabWorkflow.tsx @@ -8,7 +8,16 @@ import { type WorkflowCriteriaForm, } from '@/utils/workflow/workflowHelpers' import { workflowService, type WorkflowCriteriaDto } from '@/services/workflow.service' -import { DashboardShell } from '../workflow/DashboardShell' +import { WorkflowDesigner } from '../workflow/WorkflowDesigner' +import { SelectBoxOption } from '@/types/shared' +import { Field, FieldProps, Form, Formik } from 'formik' +import { Button, Card, FormContainer, FormItem, Input, Select } from '@/components/ui' +import { ListFormEditTabs } from '@/proxy/admin/list-form/options' +import { object, string } from 'yup' +import { useStoreState } from '@/store/store' +import { FormEditProps } from './FormEdit' +import { useLocalization } from '@/utils/hooks/useLocalization' +import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models' type PendingLink = { sourceId: string @@ -25,18 +34,33 @@ type DragEndEvent = { delta: { x: number; y: number } } -export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { +export function FormTabWorkflow( + props: FormEditProps & { + listFormCode: string + userList: SelectBoxOption[] + selectCommandColumns: DatabaseColumnDto[] + isLoadingSelectCommandColumns: boolean + }, +) { + const columnOptions: SelectBoxOption[] = props.selectCommandColumns.length + ? props.selectCommandColumns.map((column) => ({ + value: column.columnName, + label: `${column.columnName} (${column.dataType})`, + })) + : [] + const [criteria, setCriteria] = useState([]) const [selectedId, setSelectedId] = useState('') const [pendingLink, setPendingLink] = useState(null) const [criteriaForm, setCriteriaForm] = useState( - emptyCriteria('Start', listFormCode), + emptyCriteria('Start', props.listFormCode), ) const [dragPreview, setDragPreview] = useState(null) const [canvasZoom, setCanvasZoom] = useState(1) const [designerTab, setDesignerTab] = useState('flow') const [busy, setBusy] = useState(false) const canvasRef = useRef(null) + const { translate } = useLocalization() const currentCriteria = useMemo(() => criteria, [criteria]) @@ -46,10 +70,10 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { ) const loadState = useCallback(async () => { - const data = await workflowService.getState(listFormCode) + const data = await workflowService.getState(props.listFormCode) setCriteria(data.criteria) return data - }, [listFormCode]) + }, [props.listFormCode]) const runAction = useCallback( async (action: () => Promise) => { @@ -72,9 +96,9 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { if (selectedCriteria) { setCriteriaForm(toCriteriaForm(selectedCriteria)) } else { - setCriteriaForm(emptyCriteria('Start', listFormCode)) + setCriteriaForm(emptyCriteria('Start', props.listFormCode)) } - }, [listFormCode, selectedCriteria]) + }, [props.listFormCode, selectedCriteria]) useEffect(() => { if (!selectedId) return @@ -90,7 +114,7 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { runAction(async () => { await workflowService.saveCriteria({ ...normalizeCriteria(criteriaForm), - listFormCode, + listFormCode: props.listFormCode, }) setSelectedId('') }) @@ -100,8 +124,8 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { setDesignerTab('flow') runAction(async () => { const saved = await workflowService.saveCriteria({ - ...normalizeCriteria(emptyCriteria(kind, listFormCode)), - listFormCode, + ...normalizeCriteria(emptyCriteria(kind, props.listFormCode)), + listFormCode: props.listFormCode, positionX: 80 + (currentCriteria.length % 5) * 230, positionY: 220 + Math.floor(currentCriteria.length / 5) * 140, }) @@ -145,12 +169,15 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { } runAction(async () => { - await workflowService.saveCriteria({ ...normalizeCriteria(next), listFormCode }) + await workflowService.saveCriteria({ + ...normalizeCriteria(next), + listFormCode: props.listFormCode, + }) setPendingLink(null) setSelectedId(sourceId) }) }, - [busy, currentCriteria, listFormCode, runAction], + [busy, currentCriteria, props.listFormCode, runAction], ) useEffect(() => { @@ -190,7 +217,10 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { } runAction(async () => { - await workflowService.saveCriteria({ ...normalizeCriteria(next), listFormCode }) + await workflowService.saveCriteria({ + ...normalizeCriteria(next), + listFormCode: props.listFormCode, + }) setSelectedId(next.id) }) } @@ -215,7 +245,10 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { setPendingLink(null) runAction(async () => { - await workflowService.saveCriteria({ ...normalizeCriteria(next), listFormCode }) + await workflowService.saveCriteria({ + ...normalizeCriteria(next), + listFormCode: props.listFormCode, + }) setSelectedId('') }) } @@ -234,7 +267,7 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { await workflowService.saveCriteria({ ...normalizeCriteria(item), - listFormCode, + listFormCode: props.listFormCode, positionX: position.x, positionY: position.y, }) @@ -262,38 +295,149 @@ export function FormTabWorkflow({ listFormCode }: { listFormCode: string }) { setSelectedId(sourceId) } + const schema = object().shape({ + approvalFieldName: string(), + approvalDateFieldName: string(), + }) + + const initialValues = useStoreState((s) => s.admin.lists.values) + if (!initialValues) { + return null + } + return ( - - setDragPreview(event ? { id: event.active.id, delta: event.delta } : null) - } - onFitFlowLayout={fitFlowLayout} - onOpenCriteriaDetails={openCriteriaDetails} - onResetDemo={() => runAction(() => workflowService.resetDemo(listFormCode))} - onSaveCriteria={saveCriteria} - onSelectCriteria={setSelectedId} - onSetDesignerTab={setDesignerTab} - onUpdateNodePosition={updateNodePosition} - onZoomIn={() => setCanvasZoom((current) => Math.min(1.5, Number((current + 0.1).toFixed(2))))} - onZoomOut={() => - setCanvasZoom((current) => Math.max(0.6, Number((current - 0.1).toFixed(2)))) - } - /> +
+ { + await props.onSubmit(ListFormEditTabs.Workflow, values, formikHelpers) + }} + > + {({ touched, errors, values, isSubmitting }) => ( +
+ + +
+ + + {({ field, form }: FieldProps) => ( + option.value === values.workflowDto.approvalDateFieldName, + )} + onChange={(option) => form.setFieldValue(field.name, option?.value)} + /> + )} + + + + + + {({ field, form }: FieldProps) => ( + onSelectTarget(event.target.value)} - > - {targetOptions.map((option) => ( - - ))} - - ) - const toggleRow = (id: string) => onSelect(id === selectedId ? '' : id) - - return ( -
- -
-
-
-
Id
-
Tip
-
Başlık / Kural
-
Bağlantılar
-
İşlem
-
- - {criteria.length === 0 && ( -
- Seçili iş akışı için açıklama kaydı yok. -
- )} - - {criteria.map((item) => { - const isSelected = item.id === selectedId - const connectionSummary = criteriaConnectionSummary(item, criteria) - - return ( - -
toggleRow(item.id)} - > -
- {item.id} -
-
- {kindOptions.find((option) => option.value === item.kind)?.label} -
-
- {criteriaSummaryContent(item)} -
-
{connectionSummary}
-
- -
-
- {isSelected && ( -
-
- - - - - setField('title', event.target.value)} - /> - - - setField('approver', event.target.value)} - /> - - - {(form.kind === 'Start' || form.kind === 'Inform') && ( - - {targetSelect( - form.nextOnStart, - (value) => setField('nextOnStart', value), - true, - )} - - )} - - {form.kind === 'Approval' && ( - <> - - {targetSelect( - form.nextOnApprove, - (value) => setField('nextOnApprove', value), - true, - )} - - - {targetSelect( - form.nextOnReject, - (value) => setField('nextOnReject', value), - true, - )} - - - )} -
- - {form.kind === 'Compare' && ( -
-
- Karşılaştırma durumları - -
- {(form.compareOutcomes || []).map( - (outcome: CompareOutcomeDto, index: number) => ( -
-
- - updateCompareOutcome(index, { - label: event.target.value, - }) - } - /> - {targetSelect( - outcome.targetId, - (targetId) => - updateCompareOutcome(index, { - targetId, - }), - true, - )} - -
-
- {(outcome.conditions || []).map((condition, conditionIndex) => ( -
- - - - updateCompareCondition(index, conditionIndex, { - compareValue: event.target.value, - }) - } - /> - -
- ))} - -
-
- ), - )} -
- )} - -
- - -
-
- )} -
- ) - })} -
-
- -
- ) -} - -function Field({ - label, - children, - required = false, -}: { - label: string - children: React.ReactNode - required?: boolean -}) { - return ( - - ) -} - -function criteriaSummaryContent(item: WorkflowCriteriaDto) { - if (item.kind === 'Compare') { - const outcomes = item.compareOutcomes || [] - if (!outcomes.length) return '-' - - return ( -
    - {outcomes.map((outcome, index: number) => ( -
  • - {outcome.label || `Durum ${index + 1}`}:{' '} - {compareOutcomeRuleText(outcome)} -
  • - ))} -
- ) - } - - return criteriaSummary(item) -} - -function criteriaConnectionSummary(item: WorkflowCriteriaDto, criteria: WorkflowCriteriaDto[]) { - if (item.kind === 'Compare') { - const outcomes = item.compareOutcomes || [] - if (!outcomes.length) return '-' - - return ( -
    - {outcomes.map((outcome, index: number) => ( -
  • - {outcome.label || `Durum ${index + 1}`}:{' '} - {targetTitle(criteria, outcome.targetId)} -
  • - ))} -
- ) - } - - if (item.kind === 'Approval') { - return ( -
    -
  • - Onay: {targetTitle(criteria, item.nextOnApprove)} -
  • -
  • - Red: {targetTitle(criteria, item.nextOnReject)} -
  • -
- ) - } - - if (item.kind === 'Start' || item.kind === 'Inform') { - return targetTitle(criteria, item.nextOnStart) - } - - return '-' -} diff --git a/ui/src/views/admin/listForm/workflow/DashboardShell.tsx b/ui/src/views/admin/listForm/workflow/DashboardShell.tsx deleted file mode 100644 index 347e459..0000000 --- a/ui/src/views/admin/listForm/workflow/DashboardShell.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { WorkflowDesigner } from './WorkflowDesigner' -import { useEffect, useState, type FormEvent, type RefObject } from 'react' -import type { WorkflowCriteriaDto } from '@/services/workflow.service' -import { DatabaseColumnDto } from '@/proxy/sql-query-manager/models' -import { sqlObjectManagerService } from '@/services/sql-query-manager.service' - -type DashboardShellProps = { - busy: boolean - canvasRef: RefObject - canvasZoom: number - criteriaForm: any - currentCriteria: WorkflowCriteriaDto[] - designerTab: string - dragPreview: any - pendingLink: any - selectedId: string - onAddCriteria: (kind: string) => void - onBeginLink: (sourceId: string, outcome: string) => void - onChangeCriteriaForm: (form: any) => void - onClearCanvasSelection: () => void - onConnectNodes: (sourceId: string, outcome: string, targetId: string) => void - onDeleteSelectedCriteria: (criteriaId?: string) => void - onDisconnectLink: (sourceId: string, outcome: string) => void - onDragMove: (event: any) => void - onFitFlowLayout: () => void - onOpenCriteriaDetails: (id: string) => void - onResetDemo: () => void - onSaveCriteria: (event: FormEvent) => void - onSelectCriteria: (id: string) => void - onSetDesignerTab: (tab: string) => void - onUpdateNodePosition: (event: any) => void - onZoomIn: () => void - onZoomOut: () => void -} - -export function DashboardShell({ - busy, - canvasRef, - canvasZoom, - criteriaForm, - currentCriteria, - designerTab, - dragPreview, - pendingLink, - selectedId, - onAddCriteria, - onBeginLink, - onChangeCriteriaForm, - onClearCanvasSelection, - onConnectNodes, - onDeleteSelectedCriteria, - onDisconnectLink, - onDragMove, - onFitFlowLayout, - onOpenCriteriaDetails, - onResetDemo, - onSaveCriteria, - onSelectCriteria, - onSetDesignerTab, - onUpdateNodePosition, - onZoomIn, - onZoomOut, -}: DashboardShellProps) { - const [selectCommandColumns, setSelectCommandColumns] = useState([]) - const [isLoadingColumns, setIsLoadingColumns] = useState(false) - - const loadColumns = async (dsCode: string, schema: string, name: string) => { - if (!dsCode || !name) { - setSelectCommandColumns([]) - return - } - setIsLoadingColumns(true) - try { - const res = await sqlObjectManagerService.getTableColumns(dsCode, schema, name) - setSelectCommandColumns(res.data ?? []) - } catch { - setSelectCommandColumns([]) - } finally { - setIsLoadingColumns(false) - } - } - - return ( -
-
- -
-
- ) -} diff --git a/ui/src/views/admin/listForm/workflow/FlowCanvas.tsx b/ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx similarity index 99% rename from ui/src/views/admin/listForm/workflow/FlowCanvas.tsx rename to ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx index c9c3be0..6a14218 100644 --- a/ui/src/views/admin/listForm/workflow/FlowCanvas.tsx +++ b/ui/src/views/admin/listForm/workflow/WorkflowCanvas.tsx @@ -12,6 +12,7 @@ import { } from '@/utils/workflow/workflowHelpers' import type { KeyboardEvent, MouseEvent, RefObject } from 'react' import type { WorkflowCriteriaDto } from '@/services/workflow.service' +import { useLocalization } from '@/utils/hooks/useLocalization' type PendingLink = { sourceId: string @@ -36,7 +37,7 @@ type FlowNodeProps = { onBeginLink: (sourceId: string, outcome: string) => void } -export function FlowCanvas({ +export function WorkflowCanvas({ currentCriteria, dragPreview, zoom, @@ -126,7 +127,6 @@ export function FlowCanvas({ )} {currentCriteria.length === 0 && (
- Boş canvas Üstteki butonlardan adım ekleyin, sonra çıkış etiketleriyle bağlantıları kurun. @@ -286,6 +286,7 @@ function FlowNode({ top: item.positionY, transform: CSS.Translate.toString(transform), } + const { translate } = useLocalization() return ( +
+ +
+ {(formValues.compareOutcomes || []).map( + (outcome: CompareOutcomeDto, index: number) => ( +
+
+ Durum {index + 1} + Bağlantı + +
+
+ + updateCompareOutcome(index, { + label: event.target.value, + }) + } + className="flex-[5]" + /> + {targetSelect( + outcome.targetId, + (targetId) => + updateCompareOutcome(index, { + targetId, + }), + true, + 'flex-[5]', + )} + +
+ +
+ {(outcome.conditions || []).map((condition, conditionIndex) => ( +
+ + updateCompareCondition(index, conditionIndex, { + compareColumn: value, + }) + } + className="flex-[4]" + /> + + updateCompareCondition(index, conditionIndex, { + compareOperator: value, + }) + } + className="flex-[3]" + /> + + updateCompareCondition(index, conditionIndex, { + compareValue: event.target.value, + }) + } + className="flex-[3]" + /> + + + +
+ ))} +
+
+ ), + )} +
+
+ )} +
+
+ + + + + + + + + + + ) +} + +function SelectField({ + options, + value, + onChange, + required = false, + className = '', +}: { + options: SelectBoxOption[] + value: string + onChange: (value: string) => void + required?: boolean + className?: string +}) { + const selectedOption = options.find((option) => option.value === value) ?? null + + return ( + <> + undefined} + /> + )} + + ) +} + +function criteriaSummaryContent(item: WorkflowCriteriaDto) { + if (item.kind === 'Compare') { + const outcomes = item.compareOutcomes || [] + if (!outcomes.length) return '-' + + return ( +
    + {outcomes.map((outcome, index: number) => ( +
  • + {outcome.label || `Durum ${index + 1}`}:{' '} + {compareOutcomeRuleText(outcome)} +
  • + ))} +
+ ) + } + + return criteriaSummary(item) +} + +function criteriaConnectionSummary(item: WorkflowCriteriaDto, criteria: WorkflowCriteriaDto[]) { + if (item.kind === 'Compare') { + const outcomes = item.compareOutcomes || [] + if (!outcomes.length) return '-' + + return ( +
    + {outcomes.map((outcome, index: number) => ( +
  • + {outcome.label || `Durum ${index + 1}`}:{' '} + {targetTitle(criteria, outcome.targetId)} +
  • + ))} +
+ ) + } + + if (item.kind === 'Approval') { + return ( +
    +
  • + Onay: {targetTitle(criteria, item.nextOnApprove)} +
  • +
  • + Red: {targetTitle(criteria, item.nextOnReject)} +
  • +
+ ) + } + + if (item.kind === 'Start' || item.kind === 'Inform') { + return targetTitle(criteria, item.nextOnStart) + } + + return '-' +} diff --git a/ui/src/views/admin/listForm/workflow/WorkflowDesigner.tsx b/ui/src/views/admin/listForm/workflow/WorkflowDesigner.tsx index d3d1a76..74e3b57 100644 --- a/ui/src/views/admin/listForm/workflow/WorkflowDesigner.tsx +++ b/ui/src/views/admin/listForm/workflow/WorkflowDesigner.tsx @@ -2,10 +2,13 @@ import { DndContext } from '@dnd-kit/core' import classNames from 'classnames' import { FiMaximize2, FiRefreshCw, FiZoomIn, FiZoomOut } from 'react-icons/fi' import { kindIcon, kindOptions } from '@/utils/workflow/workflowConstants' -import { CriteriaTable } from './CriteriaTable' -import { FlowCanvas } from './FlowCanvas' +import { WorkflowCriteria } from './WorkflowCriteria' +import { WorkflowCanvas } from './WorkflowCanvas' import type { FormEvent, RefObject } from 'react' import type { WorkflowCriteriaDto } from '@/services/workflow.service' +import { SelectBoxOption } from '@/types/shared' +import { useLocalization } from '@/utils/hooks/useLocalization' +import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models' type WorkflowDesignerProps = { busy: boolean @@ -17,6 +20,9 @@ type WorkflowDesignerProps = { dragPreview: any pendingLink: any selectedCriteriaId: string + userList: SelectBoxOption[] + selectCommandColumns: DatabaseColumnDto[] + isLoadingSelectCommandColumns: boolean onAddCriteria: (kind: string) => void onBeginLink: (sourceId: string, outcome: string) => void onChangeCriteriaForm: (form: any) => void @@ -54,6 +60,9 @@ export function WorkflowDesigner({ dragPreview, pendingLink, selectedCriteriaId, + userList, + selectCommandColumns, + isLoadingSelectCommandColumns, onAddCriteria, onBeginLink, onChangeCriteriaForm, @@ -72,64 +81,73 @@ export function WorkflowDesigner({ onZoomIn, onZoomOut, }: WorkflowDesignerProps) { + const { translate } = useLocalization() + return ( -
-
- +
+
+
+
+ - {designerTab === 'flow' && ( - - )} -
+ {designerTab === 'flow' && ( + + )} +
- {designerTab === 'flow' && ( -
- onDragMove(null)} - onDragEnd={onUpdateNodePosition} - > - + onDragMove(null)} + onDragEnd={onUpdateNodePosition} + > + + +
+ )} + + {designerTab === 'criteria' && ( + - -
- )} - - {designerTab === 'criteria' && ( - - )} -
+ )} + + + ) } @@ -152,9 +170,11 @@ function DesignerToolbar({ onZoomIn: () => void onZoomOut: () => void }) { + const { translate } = useLocalization() + return (
- + */} ) })} @@ -219,6 +239,8 @@ function DesignerTabs({ activeTab: string onChange: (tab: string) => void }) { + const { translate } = useLocalization() + return (
)