From 38e3ef57976c680df709939578d6233a666972d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Sun, 9 Aug 2026 00:38:31 +0300 Subject: [PATCH] =?UTF-8?q?Claude=20g=C3=BCncellemesi=20SqlDataSource=20Ev?= =?UTF-8?q?ent=20geli=C5=9Ftirmesi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EntityFrameworkCore/PlatformDbContext.cs | 190 ++++----- ....cs => 20260808210009_Initial.Designer.cs} | 192 ++++----- ...1_Initial.cs => 20260808210009_Initial.cs} | 190 ++++----- .../PlatformDbContextModelSnapshot.cs | 190 ++++----- .../visualDesigner/VisualCanvas.tsx | 262 +++++++++++- ui/src/components/visualDesigner/catalog.ts | 213 +++++++++ .../visualDesigner/codeGenerator.ts | 246 ++++++++++- ui/src/components/visualDesigner/types.ts | 97 +++++ .../developerKit/VisualComponentDesigner.tsx | 403 ++++++++++++++++-- 9 files changed, 1540 insertions(+), 443 deletions(-) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20260805202101_Initial.Designer.cs => 20260808210009_Initial.Designer.cs} (98%) rename api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/{20260805202101_Initial.cs => 20260808210009_Initial.cs} (98%) diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 083c853f..5b681b8e 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -196,8 +196,8 @@ public class PlatformDbContext : b.Property(a => a.Name).IsRequired().HasMaxLength(128); b.Property(a => a.ApiUrl).HasMaxLength(256); - b.Property(a => a.Description).HasColumnType("ntext"); - b.Property(a => a.Tenants).HasColumnType("ntext"); + b.Property(a => a.Description).HasColumnType("nvarchar(max)"); + b.Property(a => a.Tenants).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.Name }).IsUnique().HasFilter(null); }); @@ -349,60 +349,60 @@ public class PlatformDbContext : b.Property(a => a.ListFormType).HasMaxLength(20); // Uzun JSON alanları için nvarchar(max) - b.Property(a => a.SelectCommand).HasColumnType("ntext"); - b.Property(a => a.SelectFieldsDefaultValueJson).HasColumnType("ntext"); + b.Property(a => a.SelectCommand).HasColumnType("nvarchar(max)"); + b.Property(a => a.SelectFieldsDefaultValueJson).HasColumnType("nvarchar(max)"); b.Property(a => a.DefaultFilter).IsUnicode(true); - b.Property(a => a.ColumnOptionJson).HasColumnType("ntext"); - b.Property(a => a.PivotOptionJson).HasColumnType("ntext"); - b.Property(a => a.FilterRowJson).HasColumnType("ntext"); - b.Property(a => a.HeaderFilterJson).HasColumnType("ntext"); - b.Property(a => a.FilterPanelJson).HasColumnType("ntext"); - b.Property(a => a.SearchPanelJson).HasColumnType("ntext"); - b.Property(a => a.GroupPanelJson).HasColumnType("ntext"); - b.Property(a => a.SelectionJson).HasColumnType("ntext"); - b.Property(a => a.PagerOptionJson).HasColumnType("ntext"); - b.Property(a => a.EditingOptionJson).HasColumnType("ntext"); - b.Property(a => a.EditingFormJson).HasColumnType("ntext"); - b.Property(a => a.PermissionJson).HasColumnType("ntext"); - b.Property(a => a.InsertFieldsDefaultValueJson).HasColumnType("ntext"); - b.Property(a => a.UpdateFieldsDefaultValueJson).HasColumnType("ntext"); - b.Property(a => a.DeleteFieldsDefaultValueJson).HasColumnType("ntext"); - b.Property(a => a.CommandColumnJson).HasColumnType("ntext"); - b.Property(a => a.StateStoringJson).HasColumnType("ntext"); - b.Property(a => a.DeleteCommand).HasColumnType("ntext"); - b.Property(a => a.UpdateCommand).HasColumnType("ntext"); - b.Property(a => a.InsertCommand).HasColumnType("ntext"); - b.Property(a => a.CustomJsSourcesJson).HasColumnType("ntext"); - b.Property(a => a.CustomStyleSourcesJson).HasColumnType("ntext"); - b.Property(a => a.FormFieldsDefaultValueJson).HasColumnType("ntext"); - b.Property(a => a.SubFormsJson).HasColumnType("ntext"); - b.Property(a => a.WidgetsJson).HasColumnType("ntext"); - b.Property(a => a.WorkflowJson).HasColumnType("ntext"); - b.Property(a => a.ExtraFilterJson).HasColumnType("ntext"); - b.Property(a => a.LayoutJson).HasColumnType("ntext"); - b.Property(a => a.TodoOptionJson).HasColumnType("ntext"); - b.Property(a => a.CommonJson).HasColumnType("ntext"); - b.Property(a => a.DataSourceJson).HasColumnType("ntext"); - b.Property(a => a.AdaptiveLayoutJson).HasColumnType("ntext"); - b.Property(a => a.AnimationJson).HasColumnType("ntext"); - b.Property(a => a.AnnotationsJson).HasColumnType("ntext"); - b.Property(a => a.ArgumentAxisJson).HasColumnType("ntext"); - b.Property(a => a.CommonAnnotationsSettingsJson).HasColumnType("ntext"); - b.Property(a => a.CommonAxisSettingsJson).HasColumnType("ntext"); - b.Property(a => a.CommonPaneSettingsJson).HasColumnType("ntext"); - b.Property(a => a.CommonSeriesSettingsJson).HasColumnType("ntext"); - b.Property(a => a.CrosshairJson).HasColumnType("ntext"); - b.Property(a => a.ExportJson).HasColumnType("ntext"); - b.Property(a => a.LegendJson).HasColumnType("ntext"); - b.Property(a => a.MarginJson).HasColumnType("ntext"); - b.Property(a => a.PanesJson).HasColumnType("ntext"); - b.Property(a => a.ScrollBarJson).HasColumnType("ntext"); - b.Property(a => a.SeriesJson).HasColumnType("ntext"); - b.Property(a => a.SizeJson).HasColumnType("ntext"); - b.Property(a => a.TitleJson).HasColumnType("ntext"); - b.Property(a => a.TooltipJson).HasColumnType("ntext"); - b.Property(a => a.ValueAxisJson).HasColumnType("ntext"); - b.Property(a => a.ZoomAndPanJson).HasColumnType("ntext"); + b.Property(a => a.ColumnOptionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PivotOptionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.FilterRowJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.HeaderFilterJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.FilterPanelJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.SearchPanelJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.GroupPanelJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.SelectionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PagerOptionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.EditingOptionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.EditingFormJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PermissionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.InsertFieldsDefaultValueJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.UpdateFieldsDefaultValueJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.DeleteFieldsDefaultValueJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CommandColumnJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.StateStoringJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.DeleteCommand).HasColumnType("nvarchar(max)"); + b.Property(a => a.UpdateCommand).HasColumnType("nvarchar(max)"); + b.Property(a => a.InsertCommand).HasColumnType("nvarchar(max)"); + b.Property(a => a.CustomJsSourcesJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CustomStyleSourcesJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.FormFieldsDefaultValueJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.SubFormsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.WidgetsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.WorkflowJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ExtraFilterJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.LayoutJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.TodoOptionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CommonJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.DataSourceJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.AdaptiveLayoutJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.AnimationJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.AnnotationsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ArgumentAxisJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CommonAnnotationsSettingsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CommonAxisSettingsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CommonPaneSettingsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CommonSeriesSettingsJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.CrosshairJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ExportJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.LegendJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.MarginJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PanesJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ScrollBarJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.SeriesJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.SizeJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.TitleJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.TooltipJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ValueAxisJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ZoomAndPanJson).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.ListFormCode }).IsUnique().HasFilter(null); @@ -438,27 +438,27 @@ public class PlatformDbContext : b.Property(a => a.BandName).HasMaxLength(128); // JSON alanlar - b.Property(a => a.ColumnFilterJson).HasColumnType("ntext"); - b.Property(a => a.ColumnHeaderJson).HasColumnType("ntext"); - b.Property(a => a.GroupingJson).HasColumnType("ntext"); - b.Property(a => a.ColumnCustomizationJson).HasColumnType("ntext"); - b.Property(a => a.TotalSummaryJson).HasColumnType("ntext"); - b.Property(a => a.GroupSummaryJson).HasColumnType("ntext"); - b.Property(a => a.JoinTableJson).HasColumnType("ntext"); - b.Property(a => a.LookupJson).HasColumnType("ntext"); - b.Property(a => a.ValidationRuleJson).HasColumnType("ntext"); - b.Property(a => a.ColumnStylingJson).HasColumnType("ntext"); - b.Property(a => a.PermissionJson).HasColumnType("ntext"); - b.Property(a => a.PivotSettingsJson).HasColumnType("ntext"); + b.Property(a => a.ColumnFilterJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ColumnHeaderJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.GroupingJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ColumnCustomizationJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.TotalSummaryJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.GroupSummaryJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.JoinTableJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.LookupJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ValidationRuleJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.ColumnStylingJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PermissionJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PivotSettingsJson).HasColumnType("nvarchar(max)"); // Stil ve format b.Property(a => a.ColumnCssClass).HasMaxLength(128); b.Property(a => a.ColumnCssValue).HasMaxLength(256); b.Property(a => a.Alignment).HasMaxLength(20).HasDefaultValue("left"); b.Property(a => a.Format).HasMaxLength(128); - b.Property(a => a.EditorOptions).HasColumnType("ntext"); + b.Property(a => a.EditorOptions).HasColumnType("nvarchar(max)"); b.Property(a => a.EditorType2).HasMaxLength(64); - b.Property(a => a.EditorScript).HasColumnType("ntext"); + b.Property(a => a.EditorScript).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.ListFormCode, x.UserId, x.RoleId, x.CultureName, x.FieldName }).IsUnique().HasFilter(null); }); @@ -472,7 +472,7 @@ public class PlatformDbContext : b.Property(a => a.UserId).HasMaxLength(256); b.Property(a => a.RoleId).HasMaxLength(256); b.Property(a => a.FilterName).HasMaxLength(128); - b.Property(a => a.CustomizationData).HasColumnType("ntext"); + b.Property(a => a.CustomizationData).HasColumnType("nvarchar(max)"); b.Property(a => a.CustomizationType).IsRequired(); }); @@ -496,7 +496,7 @@ public class PlatformDbContext : b.Property(x => x.ImportId).IsRequired(); b.Property(x => x.BlobName).IsRequired().HasMaxLength(256); b.Property(x => x.Status).IsRequired().HasMaxLength(64); - b.Property(x => x.ErrorsJson).HasColumnType("ntext"); + b.Property(x => x.ErrorsJson).HasColumnType("nvarchar(max)"); }); builder.Entity(b => @@ -519,7 +519,7 @@ public class PlatformDbContext : b.Property(x => x.NextOnReject).IsRequired().HasMaxLength(128); b.Property(x => x.PositionX).IsRequired(); b.Property(x => x.PositionY).IsRequired(); - b.Property(x => x.CompareOutcomesJson).HasColumnType("ntext"); + b.Property(x => x.CompareOutcomesJson).HasColumnType("nvarchar(max)"); }); builder.Entity(b => @@ -546,7 +546,7 @@ public class PlatformDbContext : b.Property(a => a.DataSourceCode).HasMaxLength(64); b.Property(a => a.BeforeSp).HasMaxLength(128); b.Property(a => a.AfterSp).HasMaxLength(128); - b.Property(a => a.Options).HasColumnType("ntext"); + b.Property(a => a.Options).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.Name }).IsUnique().HasFilter("[IsDeleted] = 0"); }); @@ -638,8 +638,8 @@ public class PlatformDbContext : b.Property(a => a.Method).IsRequired().HasMaxLength(10); b.Property(a => a.DataSourceCode).IsRequired().HasMaxLength(128); b.Property(a => a.Sql).IsRequired(); - b.Property(a => a.ParametersJson).HasColumnType("ntext"); - b.Property(a => a.PermissionsJson).HasColumnType("ntext"); + b.Property(a => a.ParametersJson).HasColumnType("nvarchar(max)"); + b.Property(a => a.PermissionsJson).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.TenantId, x.Name }).IsUnique().HasFilter("[IsDeleted] = 0"); }); @@ -933,9 +933,9 @@ public class PlatformDbContext : b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.About)), Prefix.DbSchema); b.ConfigureByConvention(); - b.Property(x => x.StatsJson).HasColumnType("ntext"); - b.Property(x => x.DescriptionsJson).HasColumnType("ntext"); - b.Property(x => x.SectionsJson).HasColumnType("ntext"); + b.Property(x => x.StatsJson).HasColumnType("nvarchar(max)"); + b.Property(x => x.DescriptionsJson).HasColumnType("nvarchar(max)"); + b.Property(x => x.SectionsJson).HasColumnType("nvarchar(max)"); }); builder.Entity(b => @@ -953,9 +953,9 @@ public class PlatformDbContext : b.Property(x => x.CtaTitleKey).HasMaxLength(256); b.Property(x => x.CtaSubtitleKey).HasMaxLength(256); b.Property(x => x.CtaButtonLabelKey).HasMaxLength(256); - b.Property(x => x.SlidesJson).HasColumnType("ntext"); - b.Property(x => x.FeaturesJson).HasColumnType("ntext"); - b.Property(x => x.SolutionsJson).HasColumnType("ntext"); + b.Property(x => x.SlidesJson).HasColumnType("nvarchar(max)"); + b.Property(x => x.FeaturesJson).HasColumnType("nvarchar(max)"); + b.Property(x => x.SolutionsJson).HasColumnType("nvarchar(max)"); }); builder.Entity(b => @@ -1145,9 +1145,9 @@ public class PlatformDbContext : b.Property(x => x.Email).HasMaxLength(128); b.Property(x => x.Location).HasMaxLength(256); - b.Property(x => x.BankJson).HasColumnType("ntext"); - b.Property(x => x.WorkHoursJson).HasColumnType("ntext"); - b.Property(x => x.MapJson).HasColumnType("ntext"); + b.Property(x => x.BankJson).HasColumnType("nvarchar(max)"); + b.Property(x => x.WorkHoursJson).HasColumnType("nvarchar(max)"); + b.Property(x => x.MapJson).HasColumnType("nvarchar(max)"); }); builder.Entity(b => @@ -1164,10 +1164,10 @@ public class PlatformDbContext : b.Property(x => x.Name).IsRequired().HasMaxLength(256); b.Property(x => x.DisplayName).HasMaxLength(512); b.Property(x => x.Description).HasMaxLength(2048); - b.Property(x => x.Code).IsRequired().HasColumnType("ntext"); // Uzun C# kod metni için + b.Property(x => x.Code).IsRequired().HasColumnType("nvarchar(max)"); // Uzun C# kod metni için b.Property(x => x.IsActive).IsRequired().HasDefaultValue(true); b.Property(x => x.CompilationStatus).IsRequired().HasConversion().HasMaxLength(20); - b.Property(x => x.LastCompilationError).HasColumnType("ntext"); // Uzun hata mesajları için + b.Property(x => x.LastCompilationError).HasColumnType("nvarchar(max)"); // Uzun hata mesajları için b.Property(x => x.LastSuccessfulCompilation).IsRequired(false); b.Property(x => x.Version).IsRequired().HasDefaultValue(1); b.Property(x => x.CodeHash).HasMaxLength(64); @@ -1189,7 +1189,7 @@ public class PlatformDbContext : b.Property(x => x.PublishDate).IsRequired(); b.Property(x => x.Attachments).HasMaxLength(2048); b.Property(x => x.ViewCount).HasDefaultValue(0); - b.Property(x => x.ImageUrl).HasColumnType("ntext"); + b.Property(x => x.ImageUrl).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.TenantId, x.Title }).IsUnique().HasFilter("[IsDeleted] = 0"); }); @@ -1405,7 +1405,7 @@ public class PlatformDbContext : b.Property(x => x.Description).HasMaxLength(1024); b.Property(x => x.Status).HasMaxLength(20); b.Property(x => x.isPublished).HasDefaultValue(false); - b.Property(x => x.Photos).HasColumnType("ntext"); + b.Property(x => x.Photos).HasColumnType("nvarchar(max)"); b.HasIndex(x => new { x.TenantId, x.CategoryId, x.TypeId, x.Name }).IsUnique().HasFilter("[IsDeleted] = 0"); @@ -1454,7 +1454,7 @@ public class PlatformDbContext : b.Property(x => x.Title).HasMaxLength(256); b.Property(x => x.ParticipantKey).IsRequired().HasMaxLength(512); - b.Property(x => x.ParticipantIdsJson).IsRequired().HasColumnType("ntext"); + b.Property(x => x.ParticipantIdsJson).IsRequired().HasColumnType("nvarchar(max)"); b.Property(x => x.LastMessagePreview).HasMaxLength(512); b.Property(x => x.MessageCount).HasDefaultValue(0); @@ -1471,9 +1471,9 @@ public class PlatformDbContext : b.Property(x => x.SenderUserName).IsRequired().HasMaxLength(256); b.Property(x => x.SenderName).IsRequired().HasMaxLength(256); - b.Property(x => x.RecipientIdsJson).IsRequired().HasColumnType("ntext"); + b.Property(x => x.RecipientIdsJson).IsRequired().HasColumnType("nvarchar(max)"); b.Property(x => x.Text).HasMaxLength(4096); - b.Property(x => x.AttachmentsJson).IsRequired().HasColumnType("ntext"); + b.Property(x => x.AttachmentsJson).IsRequired().HasColumnType("nvarchar(max)"); b.Property(x => x.SentAt).IsRequired(); b.HasIndex(x => new { x.TenantId, x.ConversationId, x.SentAt }); @@ -1577,7 +1577,7 @@ public class PlatformDbContext : b.Property(x => x.ResourceName).HasMaxLength(64); b.Property(x => x.MaxForms).HasDefaultValue(500); b.Property(x => x.CacheKey).HasMaxLength(512).IsRequired(); - b.Property(x => x.JsonData).IsRequired().HasColumnType("ntext"); + b.Property(x => x.JsonData).IsRequired().HasColumnType("nvarchar(max)"); b.Property(x => x.FormCount).HasDefaultValue(0); b.Property(x => x.FieldCount).HasDefaultValue(0); b.Property(x => x.JsonLength).HasDefaultValue(0); @@ -1596,7 +1596,7 @@ public class PlatformDbContext : b.Property(e => e.Title).HasMaxLength(512).IsRequired(); b.Property(e => e.Status).HasMaxLength(64).IsRequired(); - b.Property(e => e.Description).HasColumnType("ntext"); + b.Property(e => e.Description).HasColumnType("nvarchar(max)"); b.Property(e => e.Tags).HasMaxLength(256); b.Property(e => e.Assignees).HasMaxLength(512); b.Property(e => e.Priority).HasMaxLength(64); @@ -1612,10 +1612,10 @@ public class PlatformDbContext : b.Property(e => e.UserName).HasMaxLength(256).IsRequired(); b.Property(e => e.Text).HasMaxLength(512).IsRequired(); - b.Property(e => e.Description).HasColumnType("ntext"); + b.Property(e => e.Description).HasColumnType("nvarchar(max)"); b.Property(e => e.AllDay).HasDefaultValue(false); b.Property(e => e.RecurrenceRule).HasMaxLength(512); - b.Property(e => e.RecurrenceException).HasColumnType("ntext"); + b.Property(e => e.RecurrenceException).HasColumnType("nvarchar(max)"); }); ConfigureProviderSpecificModel(builder); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260805202101_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260808210009_Initial.Designer.cs similarity index 98% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260805202101_Initial.Designer.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260808210009_Initial.Designer.cs index eaf579f0..6db05ba3 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260805202101_Initial.Designer.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260808210009_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Sozsoft.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20260805202101_Initial")] + [Migration("20260808210009_Initial")] partial class Initial { /// @@ -652,7 +652,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("DescriptionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsDeleted") .ValueGeneratedOnAdd() @@ -669,10 +669,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("LastModifierId"); b.Property("SectionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("StatsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -706,7 +706,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("Description") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EndDate") .HasColumnType("datetime2"); @@ -726,7 +726,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("LastModifierId"); b.Property("RecurrenceException") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("RecurrenceRule") .HasMaxLength(512) @@ -764,7 +764,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("Description") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsActive") .HasColumnType("bit"); @@ -775,7 +775,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("Tenants") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -829,7 +829,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("datetime2"); b.Property("ImageUrl") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsDeleted") .ValueGeneratedOnAdd() @@ -1059,7 +1059,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("Options") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("WorkerType") .HasColumnType("int"); @@ -1453,7 +1453,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(512)"); b.Property("BankJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CreationTime") .HasColumnType("datetime2") @@ -1494,7 +1494,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("MapJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PhoneNumber") .HasMaxLength(20) @@ -1504,7 +1504,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("bigint"); b.Property("WorkHoursJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -1977,10 +1977,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("ParametersJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PermissionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Sql") .IsRequired() @@ -2102,7 +2102,7 @@ namespace Sozsoft.Platform.Migrations b.Property("JsonData") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("JsonLength") .ValueGeneratedOnAdd() @@ -2322,7 +2322,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("Description") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DueDate") .HasColumnType("datetime2"); @@ -2457,7 +2457,7 @@ namespace Sozsoft.Platform.Migrations b.Property("Code") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CodeHash") .HasMaxLength(64) @@ -2508,7 +2508,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("IsDeleted"); b.Property("LastCompilationError") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("LastModificationTime") .HasColumnType("datetime2") @@ -2605,7 +2605,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("Photos") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Place") .HasMaxLength(256) @@ -2936,7 +2936,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("FeaturesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FeaturesSubtitleKey") .HasMaxLength(256) @@ -2973,10 +2973,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("LastModifierId"); b.Property("SlidesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SolutionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SolutionsSubtitleKey") .HasMaxLength(256) @@ -3179,40 +3179,40 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("uniqueidentifier"); b.Property("AdaptiveLayoutJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("AnimationJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("AnnotationsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ArgumentAxisJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommandColumnJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonAnnotationsSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonAxisSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonPaneSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonSeriesSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CrosshairJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CultureName") .IsRequired() @@ -3220,17 +3220,17 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(10)"); b.Property("CustomJsSourcesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CustomStyleSourcesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DataSourceCode") .HasMaxLength(128) .HasColumnType("nvarchar(128)"); b.Property("DataSourceJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DefaultFilter") .IsUnicode(true) @@ -3243,10 +3243,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("DeleteCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DeleteFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DeleteServiceAddress") .HasMaxLength(256) @@ -3257,25 +3257,25 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(512)"); b.Property("EditingFormJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EditingOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ExportJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ExtraFilterJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FilterPanelJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FilterRowJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FormFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FullHeight") .HasColumnType("bit"); @@ -3284,10 +3284,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("GroupPanelJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("HeaderFilterJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Height") .HasColumnType("int"); @@ -3299,10 +3299,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("InsertCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("InsertFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("InsertServiceAddress") .HasMaxLength(256) @@ -3328,10 +3328,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(64)"); b.Property("LayoutJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("LegendJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ListFormCode") .IsRequired() @@ -3343,7 +3343,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(20)"); b.Property("MarginJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Name") .HasMaxLength(128) @@ -3355,16 +3355,16 @@ namespace Sozsoft.Platform.Migrations .HasDefaultValue(50); b.Property("PagerOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PanesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PermissionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PivotOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("RoleId") .HasMaxLength(256) @@ -3377,41 +3377,41 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("ScrollBarJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SearchPanelJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SelectCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SelectCommandType") .HasColumnType("int"); b.Property("SelectFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SelectionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SeriesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ShowNote") .HasColumnType("bit"); b.Property("SizeJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SortMode") .HasMaxLength(20) .HasColumnType("nvarchar(20)"); b.Property("StateStoringJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SubFormsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SubFormsListFormType") .HasColumnType("nvarchar(max)"); @@ -3425,13 +3425,13 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("TitleJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("TodoOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("TooltipJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("TreeOptionJson") .HasColumnType("nvarchar(max)"); @@ -3443,10 +3443,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("UpdateCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("UpdateFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("UpdateServiceAddress") .HasMaxLength(256) @@ -3457,19 +3457,19 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("ValueAxisJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("WidgetsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Width") .HasColumnType("int"); b.Property("WorkflowJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ZoomAndPanJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -3493,7 +3493,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("CreatorId"); b.Property("CustomizationData") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CustomizationType") .HasColumnType("int"); @@ -3590,16 +3590,16 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("ColumnCustomizationJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnFilterJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnHeaderJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnStylingJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CultureName") .IsRequired() @@ -3613,10 +3613,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("EditorOptions") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EditorScript") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EditorType2") .HasMaxLength(64) @@ -3632,10 +3632,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("GroupSummaryJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("GroupingJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsActive") .ValueGeneratedOnAdd() @@ -3643,7 +3643,7 @@ namespace Sozsoft.Platform.Migrations .HasDefaultValue(true); b.Property("JoinTableJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ListFormCode") .IsRequired() @@ -3656,13 +3656,13 @@ namespace Sozsoft.Platform.Migrations .HasDefaultValue(30); b.Property("LookupJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PermissionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PivotSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PlaceHolder") .HasMaxLength(256) @@ -3683,14 +3683,14 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("TotalSummaryJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("UserId") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); b.Property("ValidationRuleJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Visible") .ValueGeneratedOnAdd() @@ -3800,7 +3800,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("ErrorsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ExecRows") .HasColumnType("int"); @@ -3862,7 +3862,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(20)"); b.Property("CompareOutcomesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CompareValue") .HasPrecision(18, 2) @@ -4094,7 +4094,7 @@ namespace Sozsoft.Platform.Migrations b.Property("ParticipantIdsJson") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ParticipantKey") .IsRequired() @@ -4121,7 +4121,7 @@ namespace Sozsoft.Platform.Migrations b.Property("AttachmentsJson") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ConversationId") .HasColumnType("uniqueidentifier"); @@ -4158,7 +4158,7 @@ namespace Sozsoft.Platform.Migrations b.Property("RecipientIdsJson") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SenderId") .HasColumnType("uniqueidentifier"); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260805202101_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260808210009_Initial.cs similarity index 98% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260805202101_Initial.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260808210009_Initial.cs index 85b21f28..44fca048 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260805202101_Initial.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260808210009_Initial.cs @@ -489,12 +489,12 @@ namespace Sozsoft.Platform.Migrations TenantId = table.Column(type: "uniqueidentifier", nullable: true), UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), Text = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), - Description = table.Column(type: "ntext", nullable: true), + Description = table.Column(type: "nvarchar(max)", nullable: true), StartDate = table.Column(type: "datetime2", nullable: false), EndDate = table.Column(type: "datetime2", nullable: false), AllDay = table.Column(type: "bit", nullable: true, defaultValue: false), RecurrenceRule = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), - RecurrenceException = table.Column(type: "ntext", nullable: true), + RecurrenceException = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -517,7 +517,7 @@ namespace Sozsoft.Platform.Migrations Title = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), Excerpt = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), Content = table.Column(type: "nvarchar(max)", maxLength: 4096, nullable: false), - ImageUrl = table.Column(type: "ntext", nullable: true), + ImageUrl = table.Column(type: "nvarchar(max)", nullable: true), Category = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), UserId = table.Column(type: "uniqueidentifier", nullable: true), PublishDate = table.Column(type: "datetime2", nullable: false), @@ -630,7 +630,7 @@ namespace Sozsoft.Platform.Migrations TenantId = table.Column(type: "uniqueidentifier", nullable: true), Title = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ParticipantKey = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), - ParticipantIdsJson = table.Column(type: "ntext", nullable: false), + ParticipantIdsJson = table.Column(type: "nvarchar(max)", nullable: false), IsGroup = table.Column(type: "bit", nullable: false), LastSenderId = table.Column(type: "uniqueidentifier", nullable: true), LastMessagePreview = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), @@ -926,9 +926,9 @@ namespace Sozsoft.Platform.Migrations columns: table => new { Id = table.Column(type: "uniqueidentifier", nullable: false), - StatsJson = table.Column(type: "ntext", nullable: true), - DescriptionsJson = table.Column(type: "ntext", nullable: true), - SectionsJson = table.Column(type: "ntext", nullable: true), + StatsJson = table.Column(type: "nvarchar(max)", nullable: true), + DescriptionsJson = table.Column(type: "nvarchar(max)", nullable: true), + SectionsJson = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -950,8 +950,8 @@ namespace Sozsoft.Platform.Migrations Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), IsActive = table.Column(type: "bit", nullable: false), ApiUrl = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Description = table.Column(type: "ntext", nullable: true), - Tenants = table.Column(type: "ntext", nullable: true) + Description = table.Column(type: "nvarchar(max)", nullable: true), + Tenants = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -970,7 +970,7 @@ namespace Sozsoft.Platform.Migrations DataSourceCode = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), BeforeSp = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), AfterSp = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - Options = table.Column(type: "ntext", nullable: true), + Options = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -1045,9 +1045,9 @@ namespace Sozsoft.Platform.Migrations Email = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Location = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), TaxNumber = table.Column(type: "bigint", nullable: true), - BankJson = table.Column(type: "ntext", nullable: true), - WorkHoursJson = table.Column(type: "ntext", nullable: true), - MapJson = table.Column(type: "ntext", nullable: true), + BankJson = table.Column(type: "nvarchar(max)", nullable: true), + WorkHoursJson = table.Column(type: "nvarchar(max)", nullable: true), + MapJson = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -1187,8 +1187,8 @@ namespace Sozsoft.Platform.Migrations Method = table.Column(type: "nvarchar(10)", maxLength: 10, nullable: false), DataSourceCode = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), Sql = table.Column(type: "nvarchar(max)", nullable: false), - ParametersJson = table.Column(type: "ntext", nullable: true), - PermissionsJson = table.Column(type: "ntext", nullable: true), + ParametersJson = table.Column(type: "nvarchar(max)", nullable: true), + PermissionsJson = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -1237,7 +1237,7 @@ namespace Sozsoft.Platform.Migrations ResourceName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), MaxForms = table.Column(type: "int", nullable: false, defaultValue: 500), CacheKey = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), - JsonData = table.Column(type: "ntext", nullable: false), + JsonData = table.Column(type: "nvarchar(max)", nullable: false), FormCount = table.Column(type: "int", nullable: false, defaultValue: 0), FieldCount = table.Column(type: "int", nullable: false, defaultValue: 0), JsonLength = table.Column(type: "int", nullable: false, defaultValue: 0), @@ -1287,7 +1287,7 @@ namespace Sozsoft.Platform.Migrations RequestDate = table.Column(type: "datetime2", nullable: true), Title = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), Status = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - Description = table.Column(type: "ntext", nullable: true), + Description = table.Column(type: "nvarchar(max)", nullable: true), DueDate = table.Column(type: "datetime2", nullable: true), Tags = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), Assignees = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), @@ -1316,10 +1316,10 @@ namespace Sozsoft.Platform.Migrations Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), DisplayName = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), Description = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), - Code = table.Column(type: "ntext", nullable: false), + Code = table.Column(type: "nvarchar(max)", nullable: false), IsActive = table.Column(type: "bit", nullable: false, defaultValue: true), CompilationStatus = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), - LastCompilationError = table.Column(type: "ntext", nullable: true), + LastCompilationError = table.Column(type: "nvarchar(max)", nullable: true), LastSuccessfulCompilation = table.Column(type: "datetime2", nullable: true), Version = table.Column(type: "int", nullable: false, defaultValue: 1), CodeHash = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), @@ -1353,9 +1353,9 @@ namespace Sozsoft.Platform.Migrations CtaTitleKey = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), CtaSubtitleKey = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), CtaButtonLabelKey = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - SlidesJson = table.Column(type: "ntext", nullable: true), - FeaturesJson = table.Column(type: "ntext", nullable: true), - SolutionsJson = table.Column(type: "ntext", nullable: true), + SlidesJson = table.Column(type: "nvarchar(max)", nullable: true), + FeaturesJson = table.Column(type: "nvarchar(max)", nullable: true), + SolutionsJson = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -1432,10 +1432,10 @@ namespace Sozsoft.Platform.Migrations DataSourceCode = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), SelectCommandType = table.Column(type: "int", nullable: false), TableName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - SelectCommand = table.Column(type: "ntext", nullable: true), + SelectCommand = table.Column(type: "nvarchar(max)", nullable: true), KeyFieldName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), KeyFieldDbSourceType = table.Column(type: "int", nullable: false), - SelectFieldsDefaultValueJson = table.Column(type: "ntext", nullable: true), + SelectFieldsDefaultValueJson = table.Column(type: "nvarchar(max)", nullable: true), Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), Title = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), @@ -1445,43 +1445,43 @@ namespace Sozsoft.Platform.Migrations Height = table.Column(type: "int", nullable: true), FullHeight = table.Column(type: "bit", nullable: false), DefaultFilter = table.Column(type: "nvarchar(max)", nullable: true), - ColumnOptionJson = table.Column(type: "ntext", nullable: true), - PivotOptionJson = table.Column(type: "ntext", nullable: true), + ColumnOptionJson = table.Column(type: "nvarchar(max)", nullable: true), + PivotOptionJson = table.Column(type: "nvarchar(max)", nullable: true), TreeOptionJson = table.Column(type: "nvarchar(max)", nullable: true), GanttOptionJson = table.Column(type: "nvarchar(max)", nullable: true), SchedulerOptionJson = table.Column(type: "nvarchar(max)", nullable: true), - TodoOptionJson = table.Column(type: "ntext", nullable: true), - FilterRowJson = table.Column(type: "ntext", nullable: true), + TodoOptionJson = table.Column(type: "nvarchar(max)", nullable: true), + FilterRowJson = table.Column(type: "nvarchar(max)", nullable: true), RowJson = table.Column(type: "nvarchar(max)", nullable: true), - HeaderFilterJson = table.Column(type: "ntext", nullable: true), - FilterPanelJson = table.Column(type: "ntext", nullable: true), - SearchPanelJson = table.Column(type: "ntext", nullable: true), - GroupPanelJson = table.Column(type: "ntext", nullable: true), - SelectionJson = table.Column(type: "ntext", nullable: true), - PagerOptionJson = table.Column(type: "ntext", nullable: true), - EditingOptionJson = table.Column(type: "ntext", nullable: true), - EditingFormJson = table.Column(type: "ntext", nullable: true), - PermissionJson = table.Column(type: "ntext", nullable: true), - InsertFieldsDefaultValueJson = table.Column(type: "ntext", nullable: true), - UpdateFieldsDefaultValueJson = table.Column(type: "ntext", nullable: true), - DeleteFieldsDefaultValueJson = table.Column(type: "ntext", nullable: true), - CommandColumnJson = table.Column(type: "ntext", nullable: true), - StateStoringJson = table.Column(type: "ntext", nullable: true), - DeleteCommand = table.Column(type: "ntext", nullable: true), + HeaderFilterJson = table.Column(type: "nvarchar(max)", nullable: true), + FilterPanelJson = table.Column(type: "nvarchar(max)", nullable: true), + SearchPanelJson = table.Column(type: "nvarchar(max)", nullable: true), + GroupPanelJson = table.Column(type: "nvarchar(max)", nullable: true), + SelectionJson = table.Column(type: "nvarchar(max)", nullable: true), + PagerOptionJson = table.Column(type: "nvarchar(max)", nullable: true), + EditingOptionJson = table.Column(type: "nvarchar(max)", nullable: true), + EditingFormJson = table.Column(type: "nvarchar(max)", nullable: true), + PermissionJson = table.Column(type: "nvarchar(max)", nullable: true), + InsertFieldsDefaultValueJson = table.Column(type: "nvarchar(max)", nullable: true), + UpdateFieldsDefaultValueJson = table.Column(type: "nvarchar(max)", nullable: true), + DeleteFieldsDefaultValueJson = table.Column(type: "nvarchar(max)", nullable: true), + CommandColumnJson = table.Column(type: "nvarchar(max)", nullable: true), + StateStoringJson = table.Column(type: "nvarchar(max)", nullable: true), + DeleteCommand = table.Column(type: "nvarchar(max)", nullable: true), DeleteBeforeCommand = table.Column(type: "nvarchar(max)", nullable: true), DeleteAfterCommand = table.Column(type: "nvarchar(max)", nullable: true), - UpdateCommand = table.Column(type: "ntext", nullable: true), + UpdateCommand = table.Column(type: "nvarchar(max)", nullable: true), UpdateBeforeCommand = table.Column(type: "nvarchar(max)", nullable: true), UpdateAfterCommand = table.Column(type: "nvarchar(max)", nullable: true), - InsertCommand = table.Column(type: "ntext", nullable: true), + InsertCommand = table.Column(type: "nvarchar(max)", nullable: true), InsertBeforeCommand = table.Column(type: "nvarchar(max)", nullable: true), InsertAfterCommand = table.Column(type: "nvarchar(max)", nullable: true), UpdateServiceAddress = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), InsertServiceAddress = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), DeleteServiceAddress = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - CustomJsSourcesJson = table.Column(type: "ntext", nullable: true), - CustomStyleSourcesJson = table.Column(type: "ntext", nullable: true), - FormFieldsDefaultValueJson = table.Column(type: "ntext", nullable: true), + CustomJsSourcesJson = table.Column(type: "nvarchar(max)", nullable: true), + CustomStyleSourcesJson = table.Column(type: "nvarchar(max)", nullable: true), + FormFieldsDefaultValueJson = table.Column(type: "nvarchar(max)", nullable: true), IsTenant = table.Column(type: "bit", nullable: false), IsBranch = table.Column(type: "bit", nullable: false), IsOrganizationUnit = table.Column(type: "bit", nullable: false), @@ -1489,35 +1489,35 @@ namespace Sozsoft.Platform.Migrations IsSubForm = table.Column(type: "bit", nullable: false), SubFormsListFormType = table.Column(type: "nvarchar(max)", nullable: true), ShowNote = table.Column(type: "bit", nullable: false), - SubFormsJson = table.Column(type: "ntext", nullable: true), - WidgetsJson = table.Column(type: "ntext", nullable: true), - WorkflowJson = table.Column(type: "ntext", nullable: true), - ExtraFilterJson = table.Column(type: "ntext", nullable: true), - LayoutJson = table.Column(type: "ntext", nullable: true), + SubFormsJson = table.Column(type: "nvarchar(max)", nullable: true), + WidgetsJson = table.Column(type: "nvarchar(max)", nullable: true), + WorkflowJson = table.Column(type: "nvarchar(max)", nullable: true), + ExtraFilterJson = table.Column(type: "nvarchar(max)", nullable: true), + LayoutJson = table.Column(type: "nvarchar(max)", nullable: true), UserId = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), RoleId = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - CommonJson = table.Column(type: "ntext", nullable: true), - DataSourceJson = table.Column(type: "ntext", nullable: true), - AdaptiveLayoutJson = table.Column(type: "ntext", nullable: true), - AnimationJson = table.Column(type: "ntext", nullable: true), - AnnotationsJson = table.Column(type: "ntext", nullable: true), - ArgumentAxisJson = table.Column(type: "ntext", nullable: true), - CommonAnnotationsSettingsJson = table.Column(type: "ntext", nullable: true), - CommonAxisSettingsJson = table.Column(type: "ntext", nullable: true), - CommonPaneSettingsJson = table.Column(type: "ntext", nullable: true), - CommonSeriesSettingsJson = table.Column(type: "ntext", nullable: true), - CrosshairJson = table.Column(type: "ntext", nullable: true), - ExportJson = table.Column(type: "ntext", nullable: true), - LegendJson = table.Column(type: "ntext", nullable: true), - MarginJson = table.Column(type: "ntext", nullable: true), - PanesJson = table.Column(type: "ntext", nullable: true), - ScrollBarJson = table.Column(type: "ntext", nullable: true), - SeriesJson = table.Column(type: "ntext", nullable: true), - SizeJson = table.Column(type: "ntext", nullable: true), - TitleJson = table.Column(type: "ntext", nullable: true), - TooltipJson = table.Column(type: "ntext", nullable: true), - ValueAxisJson = table.Column(type: "ntext", nullable: true), - ZoomAndPanJson = table.Column(type: "ntext", nullable: true) + CommonJson = table.Column(type: "nvarchar(max)", nullable: true), + DataSourceJson = table.Column(type: "nvarchar(max)", nullable: true), + AdaptiveLayoutJson = table.Column(type: "nvarchar(max)", nullable: true), + AnimationJson = table.Column(type: "nvarchar(max)", nullable: true), + AnnotationsJson = table.Column(type: "nvarchar(max)", nullable: true), + ArgumentAxisJson = table.Column(type: "nvarchar(max)", nullable: true), + CommonAnnotationsSettingsJson = table.Column(type: "nvarchar(max)", nullable: true), + CommonAxisSettingsJson = table.Column(type: "nvarchar(max)", nullable: true), + CommonPaneSettingsJson = table.Column(type: "nvarchar(max)", nullable: true), + CommonSeriesSettingsJson = table.Column(type: "nvarchar(max)", nullable: true), + CrosshairJson = table.Column(type: "nvarchar(max)", nullable: true), + ExportJson = table.Column(type: "nvarchar(max)", nullable: true), + LegendJson = table.Column(type: "nvarchar(max)", nullable: true), + MarginJson = table.Column(type: "nvarchar(max)", nullable: true), + PanesJson = table.Column(type: "nvarchar(max)", nullable: true), + ScrollBarJson = table.Column(type: "nvarchar(max)", nullable: true), + SeriesJson = table.Column(type: "nvarchar(max)", nullable: true), + SizeJson = table.Column(type: "nvarchar(max)", nullable: true), + TitleJson = table.Column(type: "nvarchar(max)", nullable: true), + TooltipJson = table.Column(type: "nvarchar(max)", nullable: true), + ValueAxisJson = table.Column(type: "nvarchar(max)", nullable: true), + ZoomAndPanJson = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -2250,7 +2250,7 @@ namespace Sozsoft.Platform.Migrations ParticipantsCount = table.Column(type: "int", nullable: false), Likes = table.Column(type: "int", nullable: false), isPublished = table.Column(type: "bit", nullable: false, defaultValue: false), - Photos = table.Column(type: "ntext", nullable: true), + Photos = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -2286,9 +2286,9 @@ namespace Sozsoft.Platform.Migrations SenderId = table.Column(type: "uniqueidentifier", nullable: false), SenderUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), SenderName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - RecipientIdsJson = table.Column(type: "ntext", nullable: false), + RecipientIdsJson = table.Column(type: "nvarchar(max)", nullable: false), Text = table.Column(type: "nvarchar(max)", maxLength: 4096, nullable: true), - AttachmentsJson = table.Column(type: "ntext", nullable: false), + AttachmentsJson = table.Column(type: "nvarchar(max)", nullable: false), SentAt = table.Column(type: "datetime2", nullable: false), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), @@ -2789,7 +2789,7 @@ namespace Sozsoft.Platform.Migrations UserId = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), RoleId = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), FilterName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - CustomizationData = table.Column(type: "ntext", nullable: true), + CustomizationData = table.Column(type: "nvarchar(max)", nullable: true), CustomizationType = table.Column(type: "int", nullable: false), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), @@ -2833,28 +2833,28 @@ namespace Sozsoft.Platform.Migrations AllowEditing = table.Column(type: "bit", nullable: true, defaultValue: true), AllowAdding = table.Column(type: "bit", nullable: true, defaultValue: true), BandName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), - ColumnFilterJson = table.Column(type: "ntext", nullable: true), - ColumnHeaderJson = table.Column(type: "ntext", nullable: true), - GroupingJson = table.Column(type: "ntext", nullable: true), - ColumnCustomizationJson = table.Column(type: "ntext", nullable: true), - TotalSummaryJson = table.Column(type: "ntext", nullable: true), - GroupSummaryJson = table.Column(type: "ntext", nullable: true), + ColumnFilterJson = table.Column(type: "nvarchar(max)", nullable: true), + ColumnHeaderJson = table.Column(type: "nvarchar(max)", nullable: true), + GroupingJson = table.Column(type: "nvarchar(max)", nullable: true), + ColumnCustomizationJson = table.Column(type: "nvarchar(max)", nullable: true), + TotalSummaryJson = table.Column(type: "nvarchar(max)", nullable: true), + GroupSummaryJson = table.Column(type: "nvarchar(max)", nullable: true), ColumnCssClass = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), ColumnCssValue = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - JoinTableJson = table.Column(type: "ntext", nullable: true), - LookupJson = table.Column(type: "ntext", nullable: true), - ValidationRuleJson = table.Column(type: "ntext", nullable: true), - ColumnStylingJson = table.Column(type: "ntext", nullable: true), - PermissionJson = table.Column(type: "ntext", nullable: true), - PivotSettingsJson = table.Column(type: "ntext", nullable: true), + JoinTableJson = table.Column(type: "nvarchar(max)", nullable: true), + LookupJson = table.Column(type: "nvarchar(max)", nullable: true), + ValidationRuleJson = table.Column(type: "nvarchar(max)", nullable: true), + ColumnStylingJson = table.Column(type: "nvarchar(max)", nullable: true), + PermissionJson = table.Column(type: "nvarchar(max)", nullable: true), + PivotSettingsJson = table.Column(type: "nvarchar(max)", nullable: true), Alignment = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: true, defaultValue: "left"), Format = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), EditOrderNo = table.Column(type: "int", nullable: true), EditGroupOrderNo = table.Column(type: "int", nullable: true), EditorType2 = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), ColSpan = table.Column(type: "int", nullable: true), - EditorScript = table.Column(type: "ntext", nullable: true), - EditorOptions = table.Column(type: "ntext", nullable: true) + EditorScript = table.Column(type: "nvarchar(max)", nullable: true), + EditorOptions = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -2914,7 +2914,7 @@ namespace Sozsoft.Platform.Migrations NextOnReject = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), PositionX = table.Column(type: "int", nullable: false), PositionY = table.Column(type: "int", nullable: false), - CompareOutcomesJson = table.Column(type: "ntext", nullable: true) + CompareOutcomesJson = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -3392,7 +3392,7 @@ namespace Sozsoft.Platform.Migrations ValidRows = table.Column(type: "int", nullable: false), ErrorRows = table.Column(type: "int", nullable: false), Progress = table.Column(type: "float", nullable: false), - ErrorsJson = table.Column(type: "ntext", nullable: true), + ErrorsJson = table.Column(type: "nvarchar(max)", nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index 6cd5499e..91bb9bd5 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -649,7 +649,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("DescriptionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsDeleted") .ValueGeneratedOnAdd() @@ -666,10 +666,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("LastModifierId"); b.Property("SectionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("StatsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -703,7 +703,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("Description") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EndDate") .HasColumnType("datetime2"); @@ -723,7 +723,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("LastModifierId"); b.Property("RecurrenceException") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("RecurrenceRule") .HasMaxLength(512) @@ -761,7 +761,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("Description") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsActive") .HasColumnType("bit"); @@ -772,7 +772,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("Tenants") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -826,7 +826,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("datetime2"); b.Property("ImageUrl") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsDeleted") .ValueGeneratedOnAdd() @@ -1056,7 +1056,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("Options") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("WorkerType") .HasColumnType("int"); @@ -1450,7 +1450,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(512)"); b.Property("BankJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CreationTime") .HasColumnType("datetime2") @@ -1491,7 +1491,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("MapJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PhoneNumber") .HasMaxLength(20) @@ -1501,7 +1501,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("bigint"); b.Property("WorkHoursJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -1974,10 +1974,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("ParametersJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PermissionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Sql") .IsRequired() @@ -2099,7 +2099,7 @@ namespace Sozsoft.Platform.Migrations b.Property("JsonData") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("JsonLength") .ValueGeneratedOnAdd() @@ -2319,7 +2319,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("Description") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DueDate") .HasColumnType("datetime2"); @@ -2454,7 +2454,7 @@ namespace Sozsoft.Platform.Migrations b.Property("Code") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CodeHash") .HasMaxLength(64) @@ -2505,7 +2505,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("IsDeleted"); b.Property("LastCompilationError") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("LastModificationTime") .HasColumnType("datetime2") @@ -2602,7 +2602,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("Photos") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Place") .HasMaxLength(256) @@ -2933,7 +2933,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("DeletionTime"); b.Property("FeaturesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FeaturesSubtitleKey") .HasMaxLength(256) @@ -2970,10 +2970,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("LastModifierId"); b.Property("SlidesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SolutionsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SolutionsSubtitleKey") .HasMaxLength(256) @@ -3176,40 +3176,40 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("uniqueidentifier"); b.Property("AdaptiveLayoutJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("AnimationJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("AnnotationsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ArgumentAxisJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommandColumnJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonAnnotationsSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonAxisSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonPaneSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CommonSeriesSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CrosshairJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CultureName") .IsRequired() @@ -3217,17 +3217,17 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(10)"); b.Property("CustomJsSourcesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CustomStyleSourcesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DataSourceCode") .HasMaxLength(128) .HasColumnType("nvarchar(128)"); b.Property("DataSourceJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DefaultFilter") .IsUnicode(true) @@ -3240,10 +3240,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("DeleteCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DeleteFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("DeleteServiceAddress") .HasMaxLength(256) @@ -3254,25 +3254,25 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(512)"); b.Property("EditingFormJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EditingOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ExportJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ExtraFilterJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FilterPanelJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FilterRowJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FormFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("FullHeight") .HasColumnType("bit"); @@ -3281,10 +3281,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("GroupPanelJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("HeaderFilterJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Height") .HasColumnType("int"); @@ -3296,10 +3296,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("InsertCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("InsertFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("InsertServiceAddress") .HasMaxLength(256) @@ -3325,10 +3325,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(64)"); b.Property("LayoutJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("LegendJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ListFormCode") .IsRequired() @@ -3340,7 +3340,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(20)"); b.Property("MarginJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Name") .HasMaxLength(128) @@ -3352,16 +3352,16 @@ namespace Sozsoft.Platform.Migrations .HasDefaultValue(50); b.Property("PagerOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PanesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PermissionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PivotOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("RoleId") .HasMaxLength(256) @@ -3374,41 +3374,41 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("ScrollBarJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SearchPanelJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SelectCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SelectCommandType") .HasColumnType("int"); b.Property("SelectFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SelectionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SeriesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ShowNote") .HasColumnType("bit"); b.Property("SizeJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SortMode") .HasMaxLength(20) .HasColumnType("nvarchar(20)"); b.Property("StateStoringJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SubFormsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SubFormsListFormType") .HasColumnType("nvarchar(max)"); @@ -3422,13 +3422,13 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("TitleJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("TodoOptionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("TooltipJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("TreeOptionJson") .HasColumnType("nvarchar(max)"); @@ -3440,10 +3440,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(max)"); b.Property("UpdateCommand") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("UpdateFieldsDefaultValueJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("UpdateServiceAddress") .HasMaxLength(256) @@ -3454,19 +3454,19 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("ValueAxisJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("WidgetsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Width") .HasColumnType("int"); b.Property("WorkflowJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ZoomAndPanJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -3490,7 +3490,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnName("CreatorId"); b.Property("CustomizationData") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CustomizationType") .HasColumnType("int"); @@ -3587,16 +3587,16 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)"); b.Property("ColumnCustomizationJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnFilterJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnHeaderJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ColumnStylingJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CultureName") .IsRequired() @@ -3610,10 +3610,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("EditorOptions") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EditorScript") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("EditorType2") .HasMaxLength(64) @@ -3629,10 +3629,10 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(128)"); b.Property("GroupSummaryJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("GroupingJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("IsActive") .ValueGeneratedOnAdd() @@ -3640,7 +3640,7 @@ namespace Sozsoft.Platform.Migrations .HasDefaultValue(true); b.Property("JoinTableJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ListFormCode") .IsRequired() @@ -3653,13 +3653,13 @@ namespace Sozsoft.Platform.Migrations .HasDefaultValue(30); b.Property("LookupJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PermissionJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PivotSettingsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("PlaceHolder") .HasMaxLength(256) @@ -3680,14 +3680,14 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("TotalSummaryJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("UserId") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); b.Property("ValidationRuleJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("Visible") .ValueGeneratedOnAdd() @@ -3797,7 +3797,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("int"); b.Property("ErrorsJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ExecRows") .HasColumnType("int"); @@ -3859,7 +3859,7 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(20)"); b.Property("CompareOutcomesJson") - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("CompareValue") .HasPrecision(18, 2) @@ -4091,7 +4091,7 @@ namespace Sozsoft.Platform.Migrations b.Property("ParticipantIdsJson") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ParticipantKey") .IsRequired() @@ -4118,7 +4118,7 @@ namespace Sozsoft.Platform.Migrations b.Property("AttachmentsJson") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("ConversationId") .HasColumnType("uniqueidentifier"); @@ -4155,7 +4155,7 @@ namespace Sozsoft.Platform.Migrations b.Property("RecipientIdsJson") .IsRequired() - .HasColumnType("ntext"); + .HasColumnType("nvarchar(max)"); b.Property("SenderId") .HasColumnType("uniqueidentifier"); diff --git a/ui/src/components/visualDesigner/VisualCanvas.tsx b/ui/src/components/visualDesigner/VisualCanvas.tsx index 42be7055..6534c51d 100644 --- a/ui/src/components/visualDesigner/VisualCanvas.tsx +++ b/ui/src/components/visualDesigner/VisualCanvas.tsx @@ -3,6 +3,7 @@ import * as UiKit from '@/components/ui' import PlatformViewHost, { type PlatformViewName, } from '@/components/componentEditor/PlatformViewHost' +import apiService from '@/services/api.service' import { useLocalization } from '@/utils/hooks/useLocalization' import { formatLocaleValue } from '@/utils/localeFormat' import { FaArrowDown, FaArrowUp, FaClone, FaGripVertical, FaTrash } from 'react-icons/fa' @@ -147,11 +148,136 @@ const resolveUiComponent = (name: string): React.ElementType | null => { return component ? (component as React.ElementType) : null } -const executeEvent = (script: string, event: unknown, node: DesignerNode) => { +/** Prop that turns a component off; react-select spells it differently. */ +const getDisabledProperty = (type: string) => (type === 'Select' ? 'isDisabled' : 'disabled') + +export interface DesignerRefOverride { + props?: Record + hidden?: boolean +} + +/** + * Design time counterpart of the `refs` object the code generator emits. It lets + * an event script drive the other components on the canvas — value, visibility, + * enabled state, any prop — so the behaviour can be tried out before the + * component is ever saved and compiled. + */ +interface DesignerRefStore { + state: Record + nodes: Record + patch: (ref: string, override: DesignerRefOverride) => void +} + +const DesignerRefContext = React.createContext(null) + +const buildDesignerRefs = (store: DesignerRefStore | null) => { + const refs: Record = {} + if (!store) return refs + Object.entries(store.nodes).forEach(([ref, node]) => { + const overrideProps = () => store.state[ref]?.props || {} + const disabledProperty = getDisabledProperty(node.type) + const valueProperty = + 'checked' in node.props ? 'checked' : 'value' in node.props ? 'value' : 'children' + const designTimeOnly = (action: string) => () => + console.info(`refs.${ref}.${action}() yalnızca çalışma zamanında endpoint çağırır.`) + refs[ref] = { + name: ref, + type: node.type, + getValue: () => overrideProps()[valueProperty] ?? node.props[valueProperty], + setValue: (value: unknown) => store.patch(ref, { props: { [valueProperty]: value } }), + getProps: () => overrideProps(), + setProps: (patch: Record) => store.patch(ref, { props: patch || {} }), + setProp: (property: string, value: unknown) => + store.patch(ref, { props: { [property]: value } }), + isVisible: () => !store.state[ref]?.hidden, + setVisible: (visible: unknown) => store.patch(ref, { hidden: visible === false }), + show: () => store.patch(ref, { hidden: false }), + hide: () => store.patch(ref, { hidden: true }), + isEnabled: () => + (overrideProps()[disabledProperty] ?? Boolean(node.props[disabledProperty])) !== true, + setEnabled: (enabled: unknown) => + store.patch(ref, { props: { [disabledProperty]: enabled === false } }), + setReadOnly: (readOnly: unknown) => + store.patch(ref, { props: { readOnly: readOnly !== false } }), + setText: (text: unknown) => store.patch(ref, { props: { children: text } }), + reset: () => store.patch(ref, { props: null as unknown as Record }), + ...(isSqlDataSourceNode(node.type) + ? { + getRecord: () => ({}), + setField: designTimeOnly('setField'), + reload: designTimeOnly('reload'), + newRecord: designTimeOnly('newRecord'), + save: designTimeOnly('save'), + remove: designTimeOnly('remove'), + } + : {}), + } + }) + return refs +} + +const notifyFromScript = (message: unknown, type: unknown = 'info') => + UiKit.toast.push( + + {typeof message === 'string' ? message : JSON.stringify(message)} + , + { placement: 'bottom-end' }, + ) + +/** + * Design time `api`. Reads go through, exactly like the endpoint test button in + * the data panel does, so a script can be tried out on the canvas. Writes are + * refused: the designer must never insert, update or delete real records while + * a component is only being laid out. + */ +const blockedDesignTimeCall = (method: string) => (url: string) => { + console.warn(`Tasarım modunda ${method} çağrısı yapılmaz: ${url}`) + return Promise.resolve(null) +} + +const designTimeApi = { + get: (url: string, params?: Record) => + apiService.fetchData({ url, method: 'GET', params }).then((response) => response.data), + post: blockedDesignTimeCall('POST'), + put: blockedDesignTimeCall('PUT'), + patch: blockedDesignTimeCall('PATCH'), + delete: blockedDesignTimeCall('DELETE'), + remove: blockedDesignTimeCall('DELETE'), + request: (config: { url: string; method?: string }) => + String(config?.method || 'GET').toUpperCase() === 'GET' + ? apiService.fetchData(config).then((response) => response.data) + : blockedDesignTimeCall(String(config?.method))(config?.url), + errorMessage: (error: { + response?: { data?: { error?: { message?: string }; message?: string } } + message?: string + }) => + error?.response?.data?.error?.message || + error?.response?.data?.message || + error?.message || + 'İşlem tamamlanamadı.', +} + +const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor as FunctionConstructor + +const executeEvent = ( + script: string, + event: unknown, + node: DesignerNode, + refs: Record, +) => { if (!script.trim()) return try { - const run = new Function('event', 'component', 'props', script) - run(event, node, node.props) + // `await` is only legal inside an async function, and scripts that call the + // API are expected to use it. + const construct = /\bawait\b/.test(script) ? AsyncFunction : Function + const run = construct('event', 'component', 'props', 'refs', 'api', 'notify', script) + const result = run(event, node, node.props, refs, designTimeApi, notifyFromScript) + if (result instanceof Promise) { + result.catch((error) => console.error(`Designer event error (${node.type}):`, error)) + } } catch (error) { console.error(`Designer event error (${node.type}):`, error) } @@ -246,6 +372,8 @@ const getPreviewProps = ( onNodePropChange?: (id: string, propertyName: string, value: unknown) => void, translate: (key: string) => string = (key) => key, formScope?: DesignerFormScope, + refs: Record = {}, + refOverrides: Record = {}, ) => { const props: Record = {} Object.entries(node.props).forEach(([key, value]) => { @@ -267,7 +395,7 @@ const getPreviewProps = ( : undefined, } : args[0] - executeEvent(script, event, node) + executeEvent(script, event, node, refs) } }) Object.entries(node.bindings || {}).forEach(([propertyName, binding]) => { @@ -416,6 +544,9 @@ const getPreviewProps = ( } else if ('value' in props) { chainHandler('onChange', (value) => updateProp('value', eventValue(value))) } + // Applied last: a script that disabled or refilled this component has to win + // over both the toolbox defaults and the values set in the property panel. + Object.assign(props, refOverrides) props.key = node.id return props } @@ -760,6 +891,30 @@ const SqlDataSourceView = ({ ) } +/** + * A node's own content, resolved in the order the runtime uses: a `setText` + * override beats a data binding, which beats the static `children` prop. Child + * nodes are not considered here — the caller decides whether they take over. + */ +const resolveNodeContent = ( + node: DesignerNode, + dataValues: Record, + currentItem: unknown, + translate: (key: string) => string, + refOverrides: Record = {}, +): React.ReactNode => { + if (refOverrides.children !== undefined) return refOverrides.children as React.ReactNode + const childrenBinding = node.bindings?.children + const boundChildren = childrenBinding?.sourceId + ? getBindingValue(childrenBinding, dataValues, currentItem) + : undefined + if (boundChildren === null || boundChildren === undefined) { + return (resolveStaticLanguageKeys(node.props.children, translate) as React.ReactNode) || undefined + } + if (React.isValidElement(boundChildren)) return boundChildren + return typeof boundChildren === 'object' ? JSON.stringify(boundChildren) : String(boundChildren) +} + const renderElement = ( node: DesignerNode, children: React.ReactNode, @@ -770,6 +925,8 @@ const renderElement = ( onNodePropChange?: (id: string, propertyName: string, value: unknown) => void, renderCustomComponent?: (name: string, props?: Record) => React.ReactNode, formScope?: DesignerFormScope, + refs: Record = {}, + refOverrides: Record = {}, ) => { // Built in NodeView so the container can own the record state and expose it to // its children through an augmented `dataValues` map. @@ -867,21 +1024,19 @@ const renderElement = ( /> ) } - const childrenBinding = node.bindings?.children - const boundChildren = childrenBinding?.sourceId - ? getBindingValue(childrenBinding, dataValues, currentItem) - : undefined + // Own content and child nodes coexist, exactly as the generator emits them: + // the text first, then the nodes dropped underneath it. + const ownContent = resolveNodeContent(node, dataValues, currentItem, translate, refOverrides) + const hasOwnContent = ownContent !== undefined && ownContent !== null && ownContent !== '' const content: React.ReactNode = React.Children.count(children) > 0 - ? children - : boundChildren === null || boundChildren === undefined - ? (resolveStaticLanguageKeys(node.props.children, translate) as React.ReactNode) || - undefined - : React.isValidElement(boundChildren) - ? boundChildren - : typeof boundChildren === 'object' - ? JSON.stringify(boundChildren) - : String(boundChildren) + ? hasOwnContent + ? <> + {ownContent} + {children} + + : children + : ownContent const props = getPreviewProps( node, dataValues, @@ -889,6 +1044,8 @@ const renderElement = ( onNodePropChange, translate, formScope, + refs, + refOverrides, ) if (node.kind === 'custom') { return renderCustomComponent?.(node.type, { ...props, children: content }) || null @@ -1033,6 +1190,13 @@ const NodeView = ({ formScope?: DesignerFormScope }) => { const { translate } = useLocalization() + const refStore = React.useContext(DesignerRefContext) + // Rebuilt on every render so the accessors read the current override state; + // memoising it would hand the scripts a stale snapshot. + const refs = buildDesignerRefs(refStore) + const refOverride = node.ref ? refStore?.state[node.ref] : undefined + const refOverrides = refOverride?.props || {} + const refHidden = Boolean(refOverride?.hidden) const selected = interactive && selectedId === node.id // A nested node can always move: at the edge of its container it is lifted out. // Only the first/last node at the root has nowhere left to go. @@ -1123,6 +1287,8 @@ const NodeView = ({ onNodePropChange, translate, formScope, + refs, + refOverrides, ) const options = getTabOptions(tabsProps) delete tabsProps.items @@ -1421,12 +1587,17 @@ const NodeView = ({ } }, } + // While a Card holds no child node the drop target stays visible below its own + // content — otherwise a Card filled by its `children` text looks like it takes + // no components. renderElement keeps that text above whatever is passed here. const contentChildren = interactive && node.type === 'Card' && node.children.length === 0 ? [
Bileşeni buraya bırakın @@ -1434,12 +1605,16 @@ const NodeView = ({ ] : renderedChildren + // A script hid this node. In preview it is gone, exactly like at runtime; while + // designing it stays selectable so the property panel can still reach it. + if (refHidden && !interactive) return null + return (
{interactive && (
{node.type} @@ -1550,6 +1725,11 @@ const NodeView = ({
)} + {interactive && refHidden && ( + + Gizli + + )} {/* Tabs has a drop zone inside every tab, so it needs no outer placeholder. */} @@ -1603,8 +1785,45 @@ const VisualCanvas = ({ dataValues = {}, }: VisualCanvasProps) => { const previewDataValues = dataValues + const [refState, setRefState] = React.useState>({}) + const nodesByRef = React.useMemo(() => { + const map: Record = {} + const visit = (list: DesignerNode[]) => + list.forEach((node) => { + if (node.ref) map[node.ref] = node + visit(node.children || []) + }) + visit(nodes) + return map + }, [nodes]) + // Overrides are preview state, not document state: adding, removing or + // renaming a component starts from a clean sheet, while editing a property + // leaves whatever the last event script set in place. + const refFingerprint = Object.keys(nodesByRef).sort().join('|') + React.useEffect(() => setRefState({}), [refFingerprint]) + const refStore = React.useMemo( + () => ({ + state: refState, + nodes: nodesByRef, + patch: (ref, override) => + setRefState((current) => ({ + ...current, + [ref]: { + ...current[ref], + ...override, + // `props: null` resets; anything else is merged on top. + props: + override.props === null + ? {} + : { ...(current[ref]?.props || {}), ...(override.props || {}) }, + }, + })), + }), + [nodesByRef, refState], + ) return ( +
interactive && onSelect?.('')} @@ -1689,6 +1908,7 @@ const VisualCanvas = ({
)}
+ ) } diff --git a/ui/src/components/visualDesigner/catalog.ts b/ui/src/components/visualDesigner/catalog.ts index 29bc65f4..6cfb62a1 100644 --- a/ui/src/components/visualDesigner/catalog.ts +++ b/ui/src/components/visualDesigner/catalog.ts @@ -95,6 +95,10 @@ export const DESIGNER_PRIMARY_EVENTS: Record = { const DESIGNER_EVENT_SNIPPETS: Record> = { Button: { onClick: `// Butona tıklandığında çalışır. +// Sayfadaki diğer komponentlere ref adlarıyla erişebilirsiniz: +// refs.input1.setValue('Merhaba') +// refs.input1.setEnabled(false) +// refs.card1.setVisible(false) console.log('Button clicked', event)`, }, Checkbox: { @@ -131,6 +135,215 @@ console.log({ selectedValue, selectedLabel })`, }, } +/** + * The script API, as copy/paste ready examples. This is the single source of + * truth behind the designer's "Script API" panel, so anything an event script + * can do is discoverable without reading the code generator. + * + * `{{ref}}`, `{{sql}}` and `{{url}}` are replaced by the designer with real + * names from the page being edited, so a copied example runs as it is. + */ +export interface DesignerScriptRecipe { + group: string + title: string + description: string + code: string +} + +export const DESIGNER_SCRIPT_RECIPE_GROUPS = [ + 'Komponent erişimi', + 'API çağrıları', + 'SqlDataSource', + 'Event ve sayfa', +] as const + +export const DESIGNER_SCRIPT_RECIPES: DesignerScriptRecipe[] = [ + { + group: 'Komponent erişimi', + title: 'Değer atama ve okuma', + description: 'Her komponent kendi ref adıyla adreslenir.', + code: `refs.{{ref}}.setValue('Merhaba') +const value = refs.{{ref}}.getValue() +console.log(value)`, + }, + { + group: 'Komponent erişimi', + title: 'Aktif / pasif yapma', + description: 'Kaydet butonunu koşula göre kilitlemek için.', + code: `refs.{{ref}}.setEnabled(false) +console.log(refs.{{ref}}.isEnabled())`, + }, + { + group: 'Komponent erişimi', + title: 'Gösterme / gizleme', + description: 'Gizlenen komponent sayfada hiç render edilmez.', + code: `refs.{{ref}}.setVisible(false) +// veya: refs.{{ref}}.hide() / refs.{{ref}}.show()`, + }, + { + group: 'Komponent erişimi', + title: 'Salt okunur yapma', + description: 'Değeri görünür kalsın ama düzenlenemesin.', + code: `refs.{{ref}}.setReadOnly(true)`, + }, + { + group: 'Komponent erişimi', + title: 'Etiket / metin değiştirme', + description: 'Buton ve etiket yazısını çalışma anında değiştirir.', + code: `refs.{{ref}}.setText('Kaydediliyor…')`, + }, + { + group: 'Komponent erişimi', + title: 'Serbest property atama', + description: 'Property panelindeki her property script ile de yazılabilir.', + code: `refs.{{ref}}.setProps({ placeholder: 'Ara…', className: 'border-red-500' }) +refs.{{ref}}.setProp('size', 'sm')`, + }, + { + group: 'Komponent erişimi', + title: 'Script ile yapılanları geri alma', + description: 'Komponenti tasarımdaki haline döndürür.', + code: `refs.{{ref}}.reset()`, + }, + { + group: 'API çağrıları', + title: 'GET — kayıt okuma', + description: 'Sonuç doğrudan response body’sidir.', + code: `const rows = await api.get('{{url}}') +console.log(rows)`, + }, + { + group: 'API çağrıları', + title: 'GET — parametre ile', + description: 'İkinci argüman query string olarak gönderilir.', + code: `const rows = await api.get('{{url}}', { maxResultCount: 10 }) +console.log(rows)`, + }, + { + group: 'API çağrıları', + title: 'POST — yeni kayıt', + description: 'Gövde ikinci argüman olarak verilir.', + code: `const created = await api.post('{{url}}', { + name: refs.{{ref}}.getValue(), +}) +console.log(created)`, + }, + { + group: 'API çağrıları', + title: 'PUT ve DELETE', + description: 'Güncelleme ve silme aynı imzayı kullanır.', + code: `await api.put('{{url}}/5', { name: 'Yeni ad' }) +await api.delete('{{url}}/5')`, + }, + { + group: 'API çağrıları', + title: 'Hata yönetimi ve bildirim', + description: 'notify tipleri: success, info, warning, danger.', + code: `try { + await api.post('{{url}}', { name: refs.{{ref}}.getValue() }) + notify('Kayıt tamamlandı', 'success') +} catch (error) { + notify(api.errorMessage(error), 'danger') +}`, + }, + { + group: 'API çağrıları', + title: 'Çağrı boyunca butonu kilitleme', + description: 'Çift tıklamayı ve mükerrer isteği önler.', + code: `refs.{{ref}}.setEnabled(false) +refs.{{ref}}.setText('Gönderiliyor…') +try { + await api.get('{{url}}') + notify('Tamamlandı', 'success') +} catch (error) { + notify(api.errorMessage(error), 'danger') +} finally { + refs.{{ref}}.setEnabled(true) + refs.{{ref}}.setText('Gönder') +}`, + }, + { + group: 'API çağrıları', + title: 'Serbest istek', + description: 'Header, timeout gibi ayarlar gerektiğinde.', + code: `const result = await api.request({ + url: '{{url}}', + method: 'GET', + params: { skipCount: 0 }, +}) +console.log(result)`, + }, + { + group: 'SqlDataSource', + title: 'Kaydet / sil / yenile', + description: 'Toolbar’ı gizleyip kendi butonlarınızı kullanabilirsiniz.', + code: `await refs.{{sql}}.save() +// await refs.{{sql}}.remove() +// await refs.{{sql}}.reload() +// refs.{{sql}}.newRecord()`, + }, + { + group: 'SqlDataSource', + title: 'Aktif kaydı okuma ve yazma', + description: 'Alan adı Select sonucundaki sütun adıdır.', + code: `const record = refs.{{sql}}.getRecord() +console.log(record) +refs.{{sql}}.setField('name', 'Yeni ad')`, + }, + { + group: 'SqlDataSource', + title: 'Kayıtlar arasında gezinme', + description: 'Select birden fazla satır döndürdüğünde.', + code: `const rows = refs.{{sql}}.getRows() +refs.{{sql}}.goToRow(rows.length - 1)`, + }, + { + group: 'SqlDataSource', + title: 'Kaydetmeden önce doğrulama', + description: 'Zorunlu alan boşsa işlemi durdurur.', + code: `const record = refs.{{sql}}.getRecord() +if (!record.name) { + notify('Ad alanı zorunludur', 'warning') + return +} +await refs.{{sql}}.save()`, + }, + { + group: 'SqlDataSource', + title: 'Durum bilgisi', + description: 'Yeni kayıt / düzenleme, meşgul ve hata durumu.', + code: `console.log(refs.{{sql}}.getMode(), refs.{{sql}}.isBusy(), refs.{{sql}}.getError())`, + }, + { + group: 'Event ve sayfa', + title: 'Event verisi', + description: 'event içeriği komponent tipine göre değişir.', + code: `// Input: event.target.value · Checkbox: event.checked +// Select/Dropdown/Menu: seçilen değer · Button: tıklama eventi +console.log(event)`, + }, + { + group: 'Event ve sayfa', + title: 'Komponentin kendi bilgileri', + description: 'Scriptin bağlı olduğu komponent ve tasarım property’leri.', + code: `console.log(component.type, component.ref) +console.log(props)`, + }, + { + group: 'Event ve sayfa', + title: 'Sayfa yönlendirme', + description: 'Kayıt sonrası liste sayfasına dönmek için.', + code: `window.location.href = '/app/orders'`, + }, + { + group: 'Event ve sayfa', + title: 'URL parametresi okuma', + description: 'Detay sayfasında anahtar değerini almak için.', + code: `const id = new URLSearchParams(window.location.search).get('id') +console.log(id)`, + }, +] + export const getDesignerEventSnippet = (componentName: string, eventName: string) => DESIGNER_EVENT_SNIPPETS[componentName]?.[eventName] || `// ${componentName}.${eventName}(event)\nconsole.log(event)` diff --git a/ui/src/components/visualDesigner/codeGenerator.ts b/ui/src/components/visualDesigner/codeGenerator.ts index 2da0b470..069c938d 100644 --- a/ui/src/components/visualDesigner/codeGenerator.ts +++ b/ui/src/components/visualDesigner/codeGenerator.ts @@ -35,6 +35,24 @@ const safeIdentifier = (value: string) => { return /^[A-Za-z_$]/.test(cleaned) ? cleaned : `Component_${cleaned}` } +/** + * Whether the emitted component carries the `refs` runtime. It is switched on by + * `generateDesignerCode` for the whole pass when a script actually addresses + * another component, so a page that uses no refs keeps its previous output byte + * for byte instead of paying for a state hook and a guard around every node. + */ +let refRuntimeEnabled = false + +/** Prop that turns a component off; react-select spells it differently. */ +const getDisabledProperty = (type: string) => (type === 'Select' ? 'isDisabled' : 'disabled') + +/** A script with `await` in it has to be wrapped in an async function. */ +export const usesAwait = (script: string) => /\bawait\b/.test(script || '') + +const refPropsExpression = (ref: string) => `designerRefProps(${JSON.stringify(ref)})` + +const isRefControlled = (node: DesignerNode) => refRuntimeEnabled && Boolean(node.ref) + const staticValueExpression = (value: unknown): string => { if (typeof value === 'string') { return value.startsWith('::') ? `translate(${JSON.stringify(value)})` : JSON.stringify(value) @@ -142,6 +160,7 @@ const getFormScopeField = (node: DesignerNode, formScope?: FormScope) => { eventName: node.type === 'AutoComplete' ? 'onInputChange' : 'onChange', path: node.bindings[propertyName].path, setterName: formScope.setterName, + sourceId: formScope.sourceId, } } @@ -254,7 +273,10 @@ const propsToCode = ( // Spread first so anything configured on the node overrides the defaults. const leading = node.type === 'Select' ? ['{...selectMenuProps}'] : [] - const allProps = [...leading, ...props] + // …and the ref overrides spread last, because a script that disables or + // refills a component has to win over both the defaults and the design values. + const trailing = isRefControlled(node) ? [`{...${refPropsExpression(node.ref as string)}}`] : [] + const allProps = [...leading, ...props, ...trailing] return allProps.length ? ` ${allProps.join(' ')}` : '' } @@ -513,11 +535,41 @@ ${children}${toolbar}${error} ${indent('
', level)}` } +/** + * Wraps a node in its visibility guard. Tabs is the one component emitted as a + * braced expression rather than an element, so its outer `{…}` is turned into + * parentheses — inside the ternary the code is read as an expression, not as a + * JSX child. + */ +const withVisibilityGuard = (code: string, node: DesignerNode, level: number) => { + if (!isRefControlled(node)) return code + const trimmed = code.trim() + const body = + trimmed.startsWith('{') && trimmed.endsWith('}') + ? code.replace(/^(\s*)\{/, '$1(').replace(/\}(\s*)$/, ')$1') + : code + return `${indent(`{designerRefHidden(${JSON.stringify(node.ref)}) ? null : (`, level)} +${body} +${indent(')}', level)}` +} + const nodeToCode = ( node: DesignerNode, level = 0, itemVariable?: string, formScope?: FormScope, +): string => + withVisibilityGuard( + renderNodeToCode(node, isRefControlled(node) ? level + 1 : level, itemVariable, formScope), + node, + level, + ) + +const renderNodeToCode = ( + node: DesignerNode, + level = 0, + itemVariable?: string, + formScope?: FormScope, ): string => { if (isSqlDataSourceNode(node.type)) return sqlDataSourceToCode(node, level, itemVariable) if (node.type === 'Spacer') { @@ -837,17 +889,188 @@ ${indent('})()}', level)}` const nested = node.children .map((child) => nodeToCode(child, level + 1, itemVariable, formScope)) .join('\n') + // Static text is emitted through the ref override so `setText` reaches it: a + // spread `children` prop loses to JSX children, which is what a label is. + const staticText = isRefControlled(node) + ? `${refPropsExpression(node.ref as string)}.children ?? ${staticValueExpression(childrenText)}` + : staticValueExpression(childrenText) const text = childrenBinding ? indent(`{${childrenBinding}}`, level + 1) : childrenText - ? indent(`{${staticValueExpression(childrenText)}}`, level + 1) + ? indent(`{${staticText}}`, level + 1) : '' const body = [text, nested].filter(Boolean).join('\n') return `${indent(`<${tag}${propCode}>`, level)}\n${body}\n${indent(``, level)}` } +/** Every script of the document, so ref usage can be detected before emitting. */ +const collectDesignerScripts = (document: DesignerDocument) => { + const scripts: string[] = [document.lifecycle?.onMount || ''] + const visit = (nodes: DesignerNode[]) => + nodes.forEach((node) => { + Object.values(node.events || {}).forEach((script) => scripts.push(script || '')) + visit(node.children || []) + }) + visit(document.nodes) + return scripts.join('\n') +} + +interface RefTarget { + node: DesignerNode + /** Reads the node's current value, whatever holds it. */ + getExpression: string + /** Statement that writes a new value back to that same holder. */ + setStatement: string + extras: string[] +} + +/** + * `refs.` entry of a node: the value accessor is wired to whichever state + * actually owns the value — the enclosing SqlDataSource record, the node's own + * runtime state, or the ref override store for a component that has neither. + */ +const refTargetFor = ( + node: DesignerNode, + formField: ReturnType, + runtimeState: RuntimeStateSpec | null, +): RefTarget => { + const ref = node.ref as string + const extras: string[] = [] + if (isSqlDataSourceNode(node.type)) { + const names = sqlIdentifiers(node) + extras.push( + ` getRecord: () => ${names.record}`, + ` setField: (path, value) => ${names.setField}(path, value)`, + ` getRows: () => ${names.rows}`, + ` getMode: () => ${names.mode}`, + ` isBusy: () => ${names.busy}`, + ` getError: () => ${names.error}`, + ` goToRow: (index) => ${names.setIndex}(Number(index) || 0)`, + ` reload: () => ${names.refresh}()`, + ` newRecord: () => ${names.create}()`, + ` save: () => ${names.save}()`, + ` remove: () => ${names.remove}()`, + ) + return { + node, + getExpression: names.record, + setStatement: `${names.setRecord}(value)`, + extras, + } + } + if (formField) { + return { + node, + getExpression: `getByPath(data_${safeIdentifier(formField.sourceId)}, ${JSON.stringify(formField.path)})`, + setStatement: `${formField.setterName}(${JSON.stringify(formField.path)}, value)`, + extras, + } + } + if (runtimeState) { + return { + node, + getExpression: runtimeState.stateName, + setStatement: `${runtimeState.setterName}(value)`, + extras, + } + } + const valueProperty = + 'checked' in node.props ? 'checked' : 'value' in node.props ? 'value' : 'children' + return { + node, + getExpression: `${refPropsExpression(ref)}.${valueProperty} ?? ${staticValueExpression(node.props[valueProperty])}`, + setStatement: `patchDesignerRef(${JSON.stringify(ref)}, { props: { ${valueProperty}: value } })`, + extras, + } +} + +/** + * The `refs` object handed to every event script and to `onMount`. Overrides are + * kept in one state map keyed by ref name, so a script can change any prop of any + * other component without that component needing a hook of its own. + */ +const refRuntimeCode = (targets: RefTarget[]) => { + const entries = targets + .map((target) => { + const ref = target.node.ref as string + const key = JSON.stringify(ref) + const disabledProperty = JSON.stringify(getDisabledProperty(target.node.type)) + return ` ${key}: { + name: ${key}, + type: ${JSON.stringify(target.node.type)}, + getValue: () => ${target.getExpression}, + setValue: (value) => { ${target.setStatement} }, + getProps: () => designerRefProps(${key}), + setProps: (patch) => patchDesignerRef(${key}, { props: patch || {} }), + setProp: (property, value) => patchDesignerRef(${key}, { props: { [property]: value } }), + isVisible: () => !designerRefHidden(${key}), + setVisible: (visible) => patchDesignerRef(${key}, { hidden: visible === false }), + show: () => patchDesignerRef(${key}, { hidden: false }), + hide: () => patchDesignerRef(${key}, { hidden: true }), + isEnabled: () => (designerRefProps(${key})[${disabledProperty}] ?? ${JSON.stringify(Boolean(target.node.props[getDisabledProperty(target.node.type)]))}) !== true, + setEnabled: (enabled) => patchDesignerRef(${key}, { props: { [${disabledProperty}]: enabled === false } }), + setReadOnly: (readOnly) => patchDesignerRef(${key}, { props: { readOnly: readOnly !== false } }), + setText: (text) => patchDesignerRef(${key}, { props: { children: text } }), + reset: () => patchDesignerRef(${key}, { props: null, hidden: false }),${ + target.extras.length ? `\n${target.extras.join(',\n')},` : '' + } + }` + }) + .join(',\n') + + return ` // Component references. Every node on the canvas is addressable by its ref, + // so an event script can read or change another component without prop drilling. + const [designerRefState, setDesignerRefState] = React.useState({}) + const designerRefProps = (name) => designerRefState[name]?.props || {} + const designerRefHidden = (name) => Boolean(designerRefState[name]?.hidden) + const patchDesignerRef = (name, patch) => setDesignerRefState((current) => ({ + ...current, + [name]: { + ...current[name], + ...patch, + // \`props: null\` resets the overrides; anything else is merged on top. + props: patch.props === null ? {} : { ...(current[name]?.props || {}), ...(patch.props || {}) }, + }, + })) + const refs = { +${entries} + }` +} + +/** + * `api` and `notify`, the two helpers an event script needs to do something that + * is not just moving values between components. `apiService`, `toast` and + * `Notification` are already in the compiled component's scope, so this is only + * about giving the scripts a small, obvious surface over them. + */ +const SCRIPT_API_CODE = ` const api = { + get: (url, params) => apiService.fetchData({ url, method: "GET", params }).then((response) => response.data), + post: (url, data, params) => apiService.fetchData({ url, method: "POST", data, params }).then((response) => response.data), + put: (url, data, params) => apiService.fetchData({ url, method: "PUT", data, params }).then((response) => response.data), + patch: (url, data, params) => apiService.fetchData({ url, method: "PATCH", data, params }).then((response) => response.data), + delete: (url, params) => apiService.fetchData({ url, method: "DELETE", params }).then((response) => response.data), + remove: (url, params) => apiService.fetchData({ url, method: "DELETE", params }).then((response) => response.data), + request: (config) => apiService.fetchData(config).then((response) => response.data), + errorMessage: (error) => error?.response?.data?.error?.message || error?.response?.data?.message || error?.message || "İşlem tamamlanamadı.", + }` + +const SCRIPT_NOTIFY_CODE = ` const notify = (message, type = "info") => toast.push( + {typeof message === "string" ? message : JSON.stringify(message)}, + { placement: "bottom-end" }, + )` + export const generateDesignerCode = (name: string, document: DesignerDocument) => { const componentName = safeIdentifier(name || 'VisualComponent') + const scripts = collectDesignerScripts(document) + // Only pages whose scripts address a ref pay for the ref runtime. + refRuntimeEnabled = /\brefs\b/.test(scripts) + const scriptHelpers = [ + /\bapi\b/.test(scripts) ? SCRIPT_API_CODE : '', + /\bnotify\b/.test(scripts) ? SCRIPT_NOTIFY_CODE : '', + ] + .filter(Boolean) + .join('\n\n') + const refTargets: RefTarget[] = [] const handlers: string[] = [] const runtimeStateHooks: string[] = [] let hasSelect = false @@ -875,6 +1098,9 @@ export const generateDesignerCode = (name: string, document: DesignerDocument) = } const formField = getFormScopeField(node, formScope) const runtimeState = getRuntimeStateSpec(node) + if (refRuntimeEnabled && node.ref) { + refTargets.push(refTargetFor(node, formField, runtimeState)) + } if (runtimeState) { // Date pickers hold a Date in state but an ISO string in the document. const initialExpression = isDesignerDateProperty(node.type, runtimeState.propertyName) @@ -938,8 +1164,11 @@ export const generateDesignerCode = (name: string, document: DesignerDocument) = node.type === 'Checkbox' && eventName === 'onChange' ? ' const event = { checked: Boolean(valueOrEvent), originalEvent, target: originalEvent?.target }' : ' const event = valueOrEvent' + // A script that awaits an API call needs an async handler, otherwise the + // `await` is a syntax error the user only finds out about at compile time. + const asyncPrefix = usesAwait(script) ? 'async ' : '' handlers.push( - ` const handle_${safeIdentifier(node.id)}_${eventName} = (valueOrEvent, originalEvent) => {\n${stateUpdate ? ` ${stateUpdate}\n` : ''}${eventDeclaration}${script ? `\n${indent(script, 2)}` : ''}\n }`, + ` const handle_${safeIdentifier(node.id)}_${eventName} = ${asyncPrefix}(valueOrEvent, originalEvent) => {\n${stateUpdate ? ` ${stateUpdate}\n` : ''}${eventDeclaration}${script ? `\n${indent(script, 2)}` : ''}\n }`, ) }) visit( @@ -1185,12 +1414,19 @@ export const generateDesignerCode = (name: string, document: DesignerDocument) = }) .join('\n\n') + // Declared after the data/SQL/runtime state it reads, and before the handlers + // and the mount effect that call into it. + const refRuntime = refTargets.length ? refRuntimeCode(refTargets) : '' + // An effect callback must not return a promise, so an awaiting onMount is run + // through an async IIFE instead of being made async itself. const mount = document.lifecycle.onMount.trim() - ? ` React.useEffect(() => {\n${indent(document.lifecycle.onMount, 2)}\n }, [])` + ? usesAwait(document.lifecycle.onMount) + ? ` React.useEffect(() => {\n void (async () => {\n${indent(document.lifecycle.onMount, 3)}\n })()\n }, [])` + : ` React.useEffect(() => {\n${indent(document.lifecycle.onMount, 2)}\n }, [])` : '' const body = document.nodes.map((node) => nodeToCode(node, 3)).join('\n') const designerBackup = encodeURIComponent(JSON.stringify(document)) - return `/*__SOZSOFT_VISUAL_DESIGNER__${designerBackup}__*/\nconst ${componentName} = () => {\n${[dataHelpers, selectHelpers, dropdownHelpers, selectValueHelpers, selectMenuHelpers, localeHelpers, dateHelpers, tabHelpers, sqlHelpers, dataHooks, sqlHooks, ...runtimeStateHooks, mount, ...handlers].filter(Boolean).join('\n\n')}\n\n return (\n <>\n${body}\n \n )\n}\n\nexport default ${componentName}\n` + return `/*__SOZSOFT_VISUAL_DESIGNER__${designerBackup}__*/\nconst ${componentName} = () => {\n${[dataHelpers, scriptHelpers,selectHelpers, dropdownHelpers, selectValueHelpers, selectMenuHelpers, localeHelpers, dateHelpers, tabHelpers, sqlHelpers, dataHooks, sqlHooks, ...runtimeStateHooks, refRuntime, mount, ...handlers].filter(Boolean).join('\n\n')}\n\n return (\n <>\n${body}\n \n )\n}\n\nexport default ${componentName}\n` } diff --git a/ui/src/components/visualDesigner/types.ts b/ui/src/components/visualDesigner/types.ts index d3357033..eb0f636d 100644 --- a/ui/src/components/visualDesigner/types.ts +++ b/ui/src/components/visualDesigner/types.ts @@ -41,6 +41,12 @@ export interface DesignerNode { type: string kind: DesignerNodeKind slot?: string + /** + * Human readable handle of the node. Assigned automatically on every commit and + * renameable from the property panel; event scripts address each other through + * it (`refs.btnSave.setEnabled(false)`) instead of through the opaque `id`. + */ + ref?: string props: Record events: Record bindings: Record @@ -262,6 +268,97 @@ export const createEmptyDesignerDocument = ( export const createDesignerId = () => `cmp_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}` +/** + * A ref is emitted as a JavaScript property name in the generated component, so + * it has to be a plain identifier. + */ +const DESIGNER_REF_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/ + +export const isValidDesignerRef = (value: string) => DESIGNER_REF_PATTERN.test(value) + +/** `Radio.Group` → `radioGroup`, `SqlDataSource` → `sqlDataSource`, `div` → `div`. */ +export const toDesignerRefBase = (type: string) => { + const camelCased = String(type || '') + .replace(/[^A-Za-z0-9]+([A-Za-z0-9])?/g, (_match, next?: string) => + next ? next.toLocaleUpperCase('en') : '', + ) + .replace(/^[0-9]+/, '') + const base = camelCased.charAt(0).toLocaleLowerCase('en') + camelCased.slice(1) + return isValidDesignerRef(base) ? base : 'component' +} + +/** First free `` name; `taken` holds every ref already used on the page. */ +export const createDesignerRefName = (type: string, taken: Set) => { + const base = toDesignerRefBase(type) + let index = 1 + while (taken.has(`${base}${index}`)) index += 1 + return `${base}${index}` +} + +export const collectDesignerRefs = (nodes: DesignerNode[]) => { + const refs = new Map() + walkDesignerNodes(nodes, (node) => { + if (node.ref && !refs.has(node.ref)) refs.set(node.ref, node) + }) + return refs +} + +/** + * Fills in every missing or duplicated ref. Applied on each document commit, so + * a node can never end up without a unique handle however it got onto the canvas + * — toolbox drop, duplicate, drag between containers or an older saved document. + * Untouched branches keep their identity so React does not re-render them. + */ +export const withDesignerRefs = (nodes: DesignerNode[]): DesignerNode[] => { + const taken = new Set() + const assign = (list: DesignerNode[]): DesignerNode[] => { + let changed = false + const next = list.map((node) => { + const current = String(node.ref ?? '').trim() + const ref = + current && isValidDesignerRef(current) && !taken.has(current) + ? current + : createDesignerRefName(node.type, taken) + taken.add(ref) + const children = assign(node.children || []) + if (ref === node.ref && children === node.children) return node + changed = true + return { ...node, ref, children } + }) + return changed ? next : list + } + return assign(nodes) +} + +/** + * Rewrites `refs.old` / `refs["old"]` occurrences after a rename, so renaming a + * component from the property panel does not silently break the scripts that + * already drive it. + */ +export const renameDesignerRefInScript = (script: string, from: string, to: string) => { + if (!script || !from || from === to) return script + const escaped = from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + return script + .replace(new RegExp(`(\\brefs\\s*\\.\\s*)${escaped}\\b`, 'g'), `$1${to}`) + .replace(new RegExp(`(\\brefs\\s*\\[\\s*)(['"\`])${escaped}\\2(\\s*\\])`, 'g'), `$1$2${to}$2$3`) +} + +export const renameDesignerRefInNodes = ( + nodes: DesignerNode[], + from: string, + to: string, +): DesignerNode[] => + nodes.map((node) => ({ + ...node, + events: Object.fromEntries( + Object.entries(node.events || {}).map(([eventName, script]) => [ + eventName, + renameDesignerRefInScript(script, from, to), + ]), + ), + children: renameDesignerRefInNodes(node.children || [], from, to), + })) + export const walkDesignerNodes = ( nodes: DesignerNode[], callback: (node: DesignerNode, parentId: string | null) => void, diff --git a/ui/src/views/developerKit/VisualComponentDesigner.tsx b/ui/src/views/developerKit/VisualComponentDesigner.tsx index c8175bcf..b26fe400 100644 --- a/ui/src/views/developerKit/VisualComponentDesigner.tsx +++ b/ui/src/views/developerKit/VisualComponentDesigner.tsx @@ -40,16 +40,22 @@ import { Button, Notification, toast } from '@/components/ui' import StyleModal from '@/components/codeLayout/StyleModal' import VisualCanvas, { DESIGNER_DRAG_TYPE } from '@/components/visualDesigner/VisualCanvas' import { - DESIGNER_DATA_COMPONENT_NAMES, DESIGNER_PRIMARY_EVENTS, + DESIGNER_SCRIPT_RECIPES, + DESIGNER_SCRIPT_RECIPE_GROUPS, getDesignerCatalog, getDesignerEventSnippet, } from '@/components/visualDesigner/catalog' import { generateDesignerCode } from '@/components/visualDesigner/codeGenerator' import { + collectDesignerRefs, createDesignerId, createEmptyDesignerDocument, findDesignerNode, + isValidDesignerRef, + renameDesignerRefInNodes, + renameDesignerRefInScript, + withDesignerRefs, getDesignerCollectionProperty, getDesignerValueByPath, getSqlDataSourceEndpointId, @@ -150,6 +156,13 @@ const getSqlRecordFieldOrder = (propertyName: string) => const isOptionDataComponent = isDesignerOptionComponent const getOptionDataProperty = getDesignerCollectionProperty const isTabularDataComponent = isDesignerTabularComponent +/** + * The inspector's Data tab follows the toolbox category, not the collection + * registry: everything filed under `data` is expected to be data driven, even + * when it carries no collection property of its own. + */ +const isDataCategoryComponent = (definition?: DesignerComponentDefinition) => + definition?.toolboxGroup === 'data' const PROPERTY_EXAMPLE_VALUES: Record = { children: 'Örnek içerik', @@ -602,7 +615,9 @@ const normalizeDesignerDocument = (document: DesignerDocument): DesignerDocument }) return { ...document, - nodes: normalizeNodes(document.nodes), + // Documents saved before refs existed get theirs here, so every component is + // addressable from a script the moment it is opened. + nodes: withDesignerRefs(normalizeNodes(document.nodes)), canvas: { width: document.canvas?.width || 'responsive' }, // Documents saved before non-GET sources existed have no usable method value. dataSources: (Array.isArray(document.dataSources) ? document.dataSources : []).map( @@ -1124,6 +1139,14 @@ const VisualComponentDesigner = () => { const [selectedId, setSelectedId] = useState(null) const [workspaceTab, setWorkspaceTab] = useState('design') const [inspectorTab, setInspectorTab] = useState('properties') + // Editing buffer of the selected component's ref; committed on blur/Enter so a + // half typed name never lands in the document. + const [refDraft, setRefDraft] = useState('') + const [refError, setRefError] = useState('') + const [scriptApiOpen, setScriptApiOpen] = useState(false) + const [scriptApiSearch, setScriptApiSearch] = useState('') + /** Last focused event editor, so a Script API example lands in the right one. */ + const [focusedEventName, setFocusedEventName] = useState('') const [search, setSearch] = useState('') const [expandedToolboxGroups, setExpandedToolboxGroups] = useState< Record @@ -1254,7 +1277,11 @@ const VisualComponentDesigner = () => { undoStack.current.push(clone(current)) if (undoStack.current.length > 80) undoStack.current.shift() redoStack.current = [] - return updater(current) + const next = updater(current) + // Single choke point for ref assignment: whichever way a node reaches the + // document — toolbox drop, duplicate, drag or paste — it leaves here with a + // unique handle that the event scripts can address. + return { ...next, nodes: withDesignerRefs(next.nodes) } }) }, []) @@ -1320,6 +1347,93 @@ const VisualComponentDesigner = () => { [document.nodes, selectedId], ) const selectedDefinition = selectedNode ? catalogByName.get(selectedNode.type) : undefined + /** Every addressable component of the page, keyed by ref. */ + const documentRefs = useMemo(() => collectDesignerRefs(document.nodes), [document.nodes]) + + useEffect(() => { + setRefDraft(selectedNode?.ref || '') + setRefError('') + }, [selectedNode?.id, selectedNode?.ref]) + + /** + * Renames the selected component's handle and rewrites the scripts that use + * it, so `refs.button1` does not silently stop resolving once the ref is given + * a meaningful name. + */ + const commitRefRename = () => { + if (!selectedNode) return + const previous = selectedNode.ref || '' + const next = refDraft.trim() + if (!next || next === previous) { + setRefDraft(previous) + setRefError('') + return + } + if (!isValidDesignerRef(next)) { + setRefError('Ref bir JavaScript adı olmalıdır: harf ile başlamalı, boşluk içermemelidir.') + return + } + if (documentRefs.has(next)) { + setRefError('Bu ref sayfadaki başka bir komponente ait.') + return + } + setRefError('') + commitDocument((current) => ({ + ...current, + lifecycle: { onMount: renameDesignerRefInScript(current.lifecycle.onMount, previous, next) }, + nodes: renameDesignerRefInNodes( + updateNodeTree(current.nodes, selectedNode.id, (node) => ({ ...node, ref: next })), + previous, + next, + ), + })) + } + + const copyToClipboard = (text: string, message: string) => { + void navigator.clipboard?.writeText(text) + toast.push( + + {message} + , + { placement: 'bottom-end' }, + ) + } + + const copyRefName = (ref: string) => copyToClipboard(`refs.${ref}`, `refs.${ref} panoya kopyalandı.`) + + /** + * Fills the `{{ref}}` / `{{sql}}` / `{{url}}` placeholders of a Script API + * example with names that actually exist on this page, so a copied example + * runs without being edited first. + */ + const resolveRecipeCode = useCallback( + (code: string) => { + const entries = [...documentRefs.entries()] + const sqlRef = entries.find(([, node]) => isSqlDataSourceNode(node.type))?.[0] + const selectedRef = + selectedNode && !isSqlDataSourceNode(selectedNode.type) ? selectedNode.ref : undefined + const componentRef = + selectedRef || + entries.find(([, node]) => !isSqlDataSourceNode(node.type) && node.kind === 'ui')?.[0] || + entries.find(([, node]) => !isSqlDataSourceNode(node.type))?.[0] + const url = document.dataSources.find((source) => source.method === 'GET')?.url + return code + .replace(/\{\{ref\}\}/g, componentRef || 'button1') + .replace(/\{\{sql\}\}/g, sqlRef || 'sqlDataSource1') + .replace(/\{\{url\}\}/g, url || '/api/app/orders') + }, + [document.dataSources, documentRefs, selectedNode], + ) + + const filteredScriptRecipes = useMemo(() => { + const query = scriptApiSearch.trim().toLocaleLowerCase('tr') + if (!query) return DESIGNER_SCRIPT_RECIPES + return DESIGNER_SCRIPT_RECIPES.filter((recipe) => + `${recipe.group} ${recipe.title} ${recipe.description} ${recipe.code}` + .toLocaleLowerCase('tr') + .includes(query), + ) + }, [scriptApiSearch]) /** * Record of every SqlDataSource on the canvas, derived from the tested Select * endpoint. Children bind to it through the container's node id, so it is @@ -1397,9 +1511,7 @@ const VisualComponentDesigner = () => { ) const selectedIsDataComponent = Boolean( selectedNode && - (DESIGNER_DATA_COMPONENT_NAMES.has(selectedNode.type) || - selectedIsSqlDataSource || - sqlScopeNode), + (isDataCategoryComponent(selectedDefinition) || selectedIsSqlDataSource || sqlScopeNode), ) const selectedProperties = useMemo(() => { if (!selectedNode) return [] @@ -2137,6 +2249,11 @@ const VisualComponentDesigner = () => { if (event.key === 'Delete' && !isPropertyEditing && selectedId && workspaceTab === 'design') { deleteNode(selectedId) } + if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key.toLowerCase() === 'k') { + event.preventDefault() + setScriptApiOpen((current) => !current) + } + if (event.key === 'Escape') setScriptApiOpen(false) } window.addEventListener('keydown', keyHandler) return () => window.removeEventListener('keydown', keyHandler) @@ -2473,7 +2590,7 @@ const VisualComponentDesigner = () => { const dataBindableProperties = selectedNode && selectedDefinition && - (DESIGNER_DATA_COMPONENT_NAMES.has(selectedNode.type) || Boolean(sqlScopeNode)) + (isDataCategoryComponent(selectedDefinition) || Boolean(sqlScopeNode)) ? selectedDefinition.properties.filter( (property) => property.category !== 'events' && @@ -3536,6 +3653,21 @@ const VisualComponentDesigner = () => { const activeJavaScriptTarget = javascriptEventTargets.find((target) => target.node.id === selectedId) || javascriptEventTargets[0] + // A Script API example is appended to the editor the user last worked in, + // falling back to the first event of the selected component. + const activeEventName = activeJavaScriptTarget?.eventNames.includes(focusedEventName) + ? focusedEventName + : activeJavaScriptTarget?.eventNames[0] || '' + + const appendScriptToEvent = (snippet: string) => { + if (!activeJavaScriptTarget || !activeEventName) return + const current = activeJavaScriptTarget.node.events[activeEventName] || '' + updateNodeEvent( + activeJavaScriptTarget.node.id, + activeEventName, + current.trim() ? `${current.replace(/\s+$/, '')}\n\n${snippet}` : snippet, + ) + } const endpointResultText = endpointResultModal ? typeof endpointResultModal.result === 'string' ? endpointResultModal.result @@ -3737,33 +3869,53 @@ const VisualComponentDesigner = () => { ))} - {workspaceTab === 'design' && ( -
- {( - [ - ['responsive', , 'Responsive'], - ['desktop', , 'Desktop'], - ['tablet', , 'Tablet'], - ['mobile', , 'Mobile'], - ] as [DesignerDocument['canvas']['width'], React.ReactNode, string][] - ).map(([width, icon, label]) => ( - - ))} -
- )} +
+ {workspaceTab === 'design' && ( +
+ {( + [ + ['responsive', , 'Responsive'], + ['desktop', , 'Desktop'], + ['tablet', , 'Tablet'], + ['mobile', , 'Mobile'], + ] as [DesignerDocument['canvas']['width'], React.ReactNode, string][] + ).map(([width, icon, label]) => ( + + ))} +
+ )} + {/* Reachable from every tab: the examples are just as useful while + laying out the page as they are inside the event editor. */} + +
@@ -3881,6 +4033,38 @@ const VisualComponentDesigner = () => {

)}
+ {/* Every component on the page is addressable from any script, + which is what makes cross component behaviour possible. */} +
+

+ Referanslar +

+

+ Script içinden refs.ad ile erişin:{' '} + setValue, setVisible, setEnabled,{' '} + setReadOnly, setText, setProps,{' '} + getValue. +

+
+ {[...documentRefs.entries()].map(([ref, node]) => ( + + ))} + {!documentRefs.size && ( +

Henüz komponent eklenmedi.

+ )} +
+
@@ -3935,7 +4119,8 @@ const VisualComponentDesigner = () => { {activeJavaScriptTarget.eventNames.map((eventName) => (
{selectedNode.id} +
+ + Ref + + + setRefDraft(event.target.value)} + onKeyDown={(event) => { + if (event.key === 'Enter') event.currentTarget.blur() + }} + /> + {refError ? ( +

{refError}

+ ) : ( +

+ Event scriptlerinden bu isimle erişilir. Yeniden adlandırdığınızda mevcut + scriptler otomatik güncellenir. +

+ )} +
{selectedDefinition?.interfaceName && (
@@ -4135,7 +4351,7 @@ const VisualComponentDesigner = () => { > - + {snippet} Tıklayınca property değerine uygulanır. @@ -4184,6 +4400,121 @@ const VisualComponentDesigner = () => { )}
+ + {/* Everything an event script can do, as copy/paste examples filled in + with this page's own ref names and endpoints. It is a drawer rather + than a dialog on purpose: no backdrop, so the editor underneath stays + usable while an example is being read or pasted. */} + {scriptApiOpen && ( + + )} + {catalogSourceEditor && (