From fc5a4c3d7c6e1cc332ce98189bb040f22053026c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Tue, 12 Aug 2025 00:35:35 +0300 Subject: [PATCH] =?UTF-8?q?Performans=20ve=20Cors=20=C3=A7al=C4=B1=C5=9Fma?= =?UTF-8?q?s=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Seeds/PlatformDataSeeder.cs | 23 +- .../Seeds/SeederData.json | 309 +++++++++++++++--- .../Seeds/SeederDto.cs | 11 + .../Entities/CustomComponent.cs | 10 + api/src/Kurs.Platform.HttpApi.Host/Program.cs | 79 +++++ .../appsettings.Dev.json | 2 +- .../appsettings.Production.json | 3 +- ui/dev-dist/sw.js | 2 +- ui/package-lock.json | 154 ++------- ui/package.json | 14 +- ui/src/components/codeLayout/CodeEditor.tsx | 18 +- .../codeLayout/ComponentLibrary.tsx | 4 +- ui/src/views/AccessDenied.tsx | 2 +- ui/src/views/menu/MenuItemComponent.tsx | 13 +- ui/src/views/menu/MenuManager.tsx | 14 +- ui/vite.config.ts | 4 +- 16 files changed, 431 insertions(+), 231 deletions(-) diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs index a8c84554..8ed8539a 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; @@ -58,6 +59,7 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency private readonly IRepository _productRepository; private readonly IRepository _paymentMethodRepository; private readonly IRepository _installmentOptionRepository; + private readonly IRepository _customComponentRepository; public PlatformDataSeeder( @@ -93,7 +95,8 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency IRepository CustomEndpointRepository, IRepository ProductRepository, IRepository PaymentMethodRepository, - IRepository InstallmentOptionRepository + IRepository InstallmentOptionRepository, + IRepository CustomComponentRepository ) { _languages = languages; @@ -129,6 +132,7 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency _productRepository = ProductRepository; _paymentMethodRepository = PaymentMethodRepository; _installmentOptionRepository = InstallmentOptionRepository; + _customComponentRepository = CustomComponentRepository; } private static IConfigurationRoot BuildConfiguration() @@ -730,5 +734,22 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency item.Commission)); } } + + foreach (var item in items.CustomComponents) + { + var exists = await _customComponentRepository.AnyAsync(x => x.Name == item.Name); + + if (!exists) + { + await _customComponentRepository.InsertAsync(new CustomComponent( + item.Name, + item.Code, + item.Props, + item.Description, + item.IsActive, + JsonSerializer.Serialize(item.Dependencies))); + } + } } } + diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index 724681ea..f3d01b68 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -8643,7 +8643,10 @@ "descriptionKey": "Abp.Localization.DefaultLanguage.Description", "defaultValue": "en", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -8677,7 +8680,10 @@ "descriptionKey": "Abp.Localization.Timezone.Description", "defaultValue": "UTC", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -8833,7 +8839,11 @@ "descriptionKey": "App.SiteManagement.Theme.Style.Description", "defaultValue": "dx.light.compact", "isVisibleToClients": true, - "providers": ["U", "G", "D"], + "providers": [ + "U", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -8881,7 +8891,10 @@ "descriptionKey": "App.SiteManagement.General.NewMemberNotificationEmails.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -8897,7 +8910,10 @@ "descriptionKey": "App.SiteManagement.General.TimedLoginEmails.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.SiteManagement", @@ -8913,7 +8929,11 @@ "descriptionKey": "App.Sender.Sms.PostaGuvercini.Url.Description", "defaultValue": "https://www.postaguvercini.com/api_http", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -8929,7 +8949,11 @@ "descriptionKey": "App.Sender.Sms.PostaGuvercini.Username.Description", "defaultValue": "2AIlj4QlCrvlbDDBS/712A==", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": true, "mainGroupKey": "App.Sender", @@ -8945,7 +8969,11 @@ "descriptionKey": "App.Sender.Sms.PostaGuvercini.Password.Description", "defaultValue": "oTuwyZM9sxfJI+jDH5wJAw==", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": true, "mainGroupKey": "App.Sender", @@ -8961,7 +8989,11 @@ "descriptionKey": "App.Sender.WhatsApp.Url.Description", "defaultValue": "https://graph.facebook.com/v21.0", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -8977,7 +9009,11 @@ "descriptionKey": "App.Sender.WhatsApp.PhoneNumberId.Description", "defaultValue": "442035112335974", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -8993,7 +9029,11 @@ "descriptionKey": "App.Sender.WhatsApp.Token.Description", "defaultValue": "EAANoftqZAJ64BO5oPwXPqniUtNGF70u8TKvQVzGZBaYQh5UY8fYrgQkcXP9UbQUqT9PWRah1L7TzcBIiWQMacT8AkmZB33AP1begLoywIZCsQSdBSUz21GQaCowfVosYgBoXSyqH8irSBPQDLIjxxVxrC2n76SD9X6zPXeHgOqIPY92DqJXplstWrlhtZCAZDZD", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -9009,7 +9049,11 @@ "descriptionKey": "App.Sender.WhatsApp.TemplateName.Description", "defaultValue": "kurs_platform_notification", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -9025,7 +9069,10 @@ "descriptionKey": "App.Sender.Rocket.Url.Description", "defaultValue": "https://chat.sozsoft.com/api/v1", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -9041,7 +9088,10 @@ "descriptionKey": "App.Sender.Rocket.UserId.Description", "defaultValue": "LfpzPjzag4QJXm84N", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -9057,7 +9107,10 @@ "descriptionKey": "App.Sender.Rocket.Token.Description", "defaultValue": "jvqALawvXn0Q7c6FfHJV3h58DCHDfQLgFF5y7oIc7oc", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "App.Sender", @@ -9073,7 +9126,11 @@ "descriptionKey": "Abp.Mailing.DefaultFromDisplayName.Description", "defaultValue": "Kurs", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9089,7 +9146,11 @@ "descriptionKey": "Abp.Mailing.DefaultFromAddress.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9105,7 +9166,11 @@ "descriptionKey": "Abp.Mailing.Smtp.UserName.Description", "defaultValue": "system@sozsoft.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9121,7 +9186,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Password.Description", "defaultValue": "QT9L7BCl1CT/1Hq19HoSlQ==", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": true, "mainGroupKey": "Abp.Mailing", @@ -9137,7 +9206,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Host.Description", "defaultValue": "127.0.0.1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9153,7 +9226,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Port.Description", "defaultValue": "25", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9169,7 +9246,11 @@ "descriptionKey": "Abp.Mailing.Smtp.Domain.Description", "defaultValue": "sozsoft.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9185,7 +9266,11 @@ "descriptionKey": "Abp.Mailing.Smtp.EnableSsl.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9201,7 +9286,11 @@ "descriptionKey": "Abp.Mailing.AWS.Profile.Description", "defaultValue": "mail-sdk-user", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9217,7 +9306,11 @@ "descriptionKey": "Abp.Mailing.AWS.Region.Description", "defaultValue": "eu-central-1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9233,7 +9326,11 @@ "descriptionKey": "Abp.Mailing.AWS.AccessKey.Description", "defaultValue": "aXW8L21rP6dPO6Txj76Be2FCpWRBa25EMrSAVL76", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9249,7 +9346,11 @@ "descriptionKey": "Abp.Mailing.AWS.AccessKeyId.Description", "defaultValue": "AKIATULUYBLX4IY3S2P1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Mailing", @@ -9265,7 +9366,10 @@ "descriptionKey": "Abp.Account.IsSelfRegistrationEnabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9281,7 +9385,10 @@ "descriptionKey": "Abp.Account.EnableLocalLogin.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9297,7 +9404,11 @@ "descriptionKey": "Abp.Account.TwoFactor.Enabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9313,7 +9424,10 @@ "descriptionKey": "Abp.Account.Captcha.MaxFailedAccessAttempts.Description", "defaultValue": "3", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9329,7 +9443,10 @@ "descriptionKey": "Abp.Account.Captcha.EndPoint.Description", "defaultValue": "https://challenges.cloudflare.com/turnstile/v0/siteverify", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9345,7 +9462,10 @@ "descriptionKey": "Abp.Account.Captcha.SiteKey.Description", "defaultValue": "0x4AAAAAAAGadwQME-GSYuJU", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9361,7 +9481,10 @@ "descriptionKey": "Abp.Account.Captcha.SecretKey.Description", "defaultValue": "0x4AAAAAAAGad_f_WP47IcNBs9FTu5DhNX8", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Account", @@ -9377,7 +9500,11 @@ "descriptionKey": "Abp.Identity.Profile.General.RequireVerifiedAccount.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9393,7 +9520,11 @@ "descriptionKey": "Abp.Identity.Profile.General.BlacklistedEmailProviders.Description", "defaultValue": "gmail.com\r\nyahoo.com\r\nhotmail.com", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9409,7 +9540,11 @@ "descriptionKey": "Abp.Identity.Password.ForceUsersToPeriodicallyChangePassword.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9425,7 +9560,11 @@ "descriptionKey": "Abp.Identity.Password.PasswordChangePeriodDays.Description", "defaultValue": "0", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9441,7 +9580,11 @@ "descriptionKey": "Abp.Identity.Password.RequiredLength.Description", "defaultValue": "6", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9457,7 +9600,11 @@ "descriptionKey": "Abp.Identity.Password.RequiredUniqueChars.Description", "defaultValue": "1", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9473,7 +9620,11 @@ "descriptionKey": "Abp.Identity.Password.RequireNonAlphanumeric.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9489,7 +9640,11 @@ "descriptionKey": "Abp.Identity.Password.RequireLowercase.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9505,7 +9660,11 @@ "descriptionKey": "Abp.Identity.Password.RequireUppercase.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9521,7 +9680,11 @@ "descriptionKey": "Abp.Identity.Password.RequireDigit.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9537,7 +9700,11 @@ "descriptionKey": "Abp.Identity.Lockout.AllowedForNewUsers.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9553,7 +9720,11 @@ "descriptionKey": "Abp.Identity.Lockout.LockoutDuration.Description", "defaultValue": "300", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9569,7 +9740,11 @@ "descriptionKey": "Abp.Identity.Lockout.MaxFailedAccessAttempts.Description", "defaultValue": "5", "isVisibleToClients": false, - "providers": ["T", "G", "D"], + "providers": [ + "T", + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9585,7 +9760,10 @@ "descriptionKey": "Abp.Identity.SignIn.RequireConfirmedEmail.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9601,7 +9779,10 @@ "descriptionKey": "Abp.Identity.SignIn.RequireConfirmedPhoneNumber.Description", "defaultValue": "False", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9617,7 +9798,10 @@ "descriptionKey": "Abp.Identity.User.IsUserNameUpdateEnabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -9633,7 +9817,10 @@ "descriptionKey": "Abp.Identity.User.IsEmailUpdateEnabled.Description", "defaultValue": "True", "isVisibleToClients": false, - "providers": ["G", "D"], + "providers": [ + "G", + "D" + ], "isInherited": false, "isEncrypted": false, "mainGroupKey": "Abp.Identity", @@ -25775,5 +25962,23 @@ "name": "12 Taksit", "commission": 0.275 } + ], + "CustomComponents": [ + { + "name": "AxiosListComponent", + "code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface AxiosListComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\", // defaults'ı her seferinde set etme\n});\n\nconst AxiosListComponent: React.FC = ({ title }) => {\n const [data, setData] = useState>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/dynamic/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return
Loading...
;\n if (error) return
Error: {error}
;\n if (!data.length) return
No records found
;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n
\n \n \n \n {headers.map((key) => (\n \n {key === \"actions\" ? \"Actions\" : key}\n \n ))}\n \n \n \n {data.map((item, rowIndex) => (\n \n \n \n \n \n ))}\n \n
\n {item.id}\n \n {item.name}\n \n alert(item.name)}\n className=\"bg-blue-600 hover:bg-blue-700 text-white text-sm px-3 py-1 rounded-lg shadow-sm transition\"\n >\n Show Name\n \n
\n
\n );\n};\n\nexport default AxiosListComponent;", + "props": null, + "description": null, + "isActive": true, + "dependencies": [] + }, + { + "name": "EntityListComponent", + "code": "const EntityListComponent = ({\n title = \"Product\"\n}) => {\n return (\n \n );\n};\n\nexport default EntityListComponent;", + "props": null, + "description": null, + "isActive": true, + "dependencies": ["AxiosListComponent"] + } ] -} +} \ No newline at end of file diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs index 1836ae91..e0221d4e 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs @@ -42,6 +42,7 @@ public class SeederDto public List Products { get; set; } public List PaymentMethods { get; set; } public List InstallmentOptions { get; set; } + public List CustomComponents { get; set; } } public class ChartsSeedDto @@ -298,3 +299,13 @@ public class InstallmentOptionSeedDto public string Name { get; set; } // e.g. "Tek Çekim", "2 Taksit" public decimal Commission { get; set; } } + +public class CustomComponentSeedDto +{ + public string Name { get; set; } + public string Code { get; set; } + public string? Props { get; set; } + public string? Description { get; set; } + public bool IsActive { get; set; } + public List Dependencies { get; set; } = new(); +} diff --git a/api/src/Kurs.Platform.Domain/Entities/CustomComponent.cs b/api/src/Kurs.Platform.Domain/Entities/CustomComponent.cs index 09b9e7cf..0b5e106d 100644 --- a/api/src/Kurs.Platform.Domain/Entities/CustomComponent.cs +++ b/api/src/Kurs.Platform.Domain/Entities/CustomComponent.cs @@ -13,4 +13,14 @@ public class CustomComponent : FullAuditedEntity, IMultiTenant public string? Description { get; set; } public bool IsActive { get; set; } = true; public string? Dependencies { get; set; } // JSON string of component names + + public CustomComponent(string name, string code, string? props, string? description, bool isActive, string? dependencies) + { + Name = name; + Code = code; + Props = props; + Description = description; + IsActive = isActive; + Dependencies = dependencies; + } } diff --git a/api/src/Kurs.Platform.HttpApi.Host/Program.cs b/api/src/Kurs.Platform.HttpApi.Host/Program.cs index 0128890b..cc894f3f 100644 --- a/api/src/Kurs.Platform.HttpApi.Host/Program.cs +++ b/api/src/Kurs.Platform.HttpApi.Host/Program.cs @@ -73,7 +73,86 @@ public class Program .UseAutofac() .UseSerilog(); await builder.AddApplicationAsync(); + + var baseDomain = builder.Configuration["App:BaseDomain"]?.Trim(); + var extraOrigins = (builder.Configuration["App:CorsOrigins"] ?? "") + .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + // Her ortamda tek policy tanımla; kuralları içeride ayır + builder.Services.AddCors(options => + { + options.AddPolicy("Dynamic", policy => + { + policy + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials() + .SetIsOriginAllowed(origin => + { + if (!Uri.TryCreate(origin, UriKind.Absolute, out var uri)) + return false; + + var scheme = uri.Scheme.ToLowerInvariant(); + var host = uri.Host.ToLowerInvariant(); + + if (builder.Environment.IsProduction()) + { + // PROD: sadece HTTPS + *.baseDomain + (isteğe bağlı) extraOrigins + if (scheme != "https") return false; + + if (!string.IsNullOrWhiteSpace(baseDomain)) + { + var bd = baseDomain.ToLowerInvariant(); + if (host == bd || host.EndsWith("." + bd)) + return true; + } + + // App:CorsOrigins içindeki tam domainleri de kabul et + foreach (var o in extraOrigins) + { + if (Uri.TryCreate(o, UriKind.Absolute, out var eo) + && eo.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) + && eo.Host.Equals(host, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + else + { + // DEV/LOCAL: localhost ve dev-* subdomainleri + if (host == "localhost" || host == "127.0.0.1" || host == "[::1]") + return true; + + // Örn. dev-*.sozsoft.com gibi bir pattern istiyorsan: + if (!string.IsNullOrWhiteSpace(baseDomain) && + (host.StartsWith("dev-") && host.EndsWith("." + baseDomain!.ToLowerInvariant()))) + return true; + + // İstersen http de kabul et (vite genelde http çalışır) + if (scheme == "http" && (host == "localhost" || host == "127.0.0.1")) + return true; + + // İsteğe bağlı: extraOrigins development’ta da geçerli olsun dersen: + foreach (var o in extraOrigins) + { + if (Uri.TryCreate(o, UriKind.Absolute, out var eo) + && eo.Host.Equals(host, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + }); + }); + }); + var app = builder.Build(); + app.UseCors("Dynamic"); await app.InitializeApplicationAsync(); await app.RunAsync(); return 0; diff --git a/api/src/Kurs.Platform.HttpApi.Host/appsettings.Dev.json b/api/src/Kurs.Platform.HttpApi.Host/appsettings.Dev.json index 42b8a450..b1d13239 100644 --- a/api/src/Kurs.Platform.HttpApi.Host/appsettings.Dev.json +++ b/api/src/Kurs.Platform.HttpApi.Host/appsettings.Dev.json @@ -2,7 +2,7 @@ "App": { "SelfUrl": "https://dev-api.sozsoft.com", "ClientUrl": "https://dev.sozsoft.com", - "CorsOrigins": "https://sozsoft.com,https://dev.sozsoft.com", + "CorsOrigins": "https://dev.sozsoft.com", "RedirectAllowedUrls": "https://dev.sozsoft.com,https://dev.sozsoft.com/authentication/callback", "AttachmentsPath": "/etc/api/mail-queue/attachments", "CdnPath": "/etc/api/cdn", diff --git a/api/src/Kurs.Platform.HttpApi.Host/appsettings.Production.json b/api/src/Kurs.Platform.HttpApi.Host/appsettings.Production.json index 6f91fa80..d67f11bd 100644 --- a/api/src/Kurs.Platform.HttpApi.Host/appsettings.Production.json +++ b/api/src/Kurs.Platform.HttpApi.Host/appsettings.Production.json @@ -2,7 +2,8 @@ "App": { "SelfUrl": "https://api.sozsoft.com", "ClientUrl": "https://sozsoft.com", - "CorsOrigins": "https://sozsoft.com,https://sozsoft.com,https://demo.sozsoft.com", + "BaseDomain": "sozsoft.com", + "CorsOrigins": "https://sozsoft.com", "RedirectAllowedUrls": "https://sozsoft.com,https://sozsoft.com/authentication/callback", "AttachmentsPath": "/etc/api/mail-queue/attachments", "CdnPath": "/etc/api/cdn", diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js index 4b15efd4..098df024 100644 --- a/ui/dev-dist/sw.js +++ b/ui/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.fduoepfh2f" + "revision": "0.1u96j36821" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/ui/package-lock.json b/ui/package-lock.json index 21f8ee37..6378de11 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -64,27 +64,21 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@tailwindcss/typography": "^0.5.15", "@types/babel__standalone": "^7.1.9", - "@types/d3-fetch": "^3.0.2", - "@types/d3-scale": "^4.0.3", "@types/file-saver": "^2.0.7", "@types/lodash": "^4.14.191", "@types/node": "^18.15.5", - "@types/qs": "^6.9.7", "@types/react": "^18.3.18", - "@types/react-beautiful-dnd": "^13.1.4", "@types/react-dom": "^18.3.5", "@types/react-helmet": "^6.1.9", "@types/react-highlight-words": "^0.16.4", "@types/react-modal": "^3.13.1", - "@types/react-portal": "^4.0.4", - "@types/react-scroll": "^1.8.7", - "@types/react-simple-maps": "^3.0.6", - "@types/react-syntax-highlighter": "^15.5.6", "@types/redux-state-sync": "^3.1.9", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.14", + "browserslist": "^4.25.2", + "caniuse-lite": "^1.0.30001734", "cross-env": "^7.0.3", "cssnano": "^6.0.1", "dotenv": "^16.0.3", @@ -2458,67 +2452,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/d3-color": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-dsv": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-fetch": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/d3-dsv": "*" - } - }, - "node_modules/@types/d3-geo": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-interpolate": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/d3-color": "^2" - } - }, - "node_modules/@types/d3-scale": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-selection": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-time": { - "version": "3.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-zoom": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/d3-interpolate": "^2", - "@types/d3-selection": "^2" - } - }, "node_modules/@types/estree": { "version": "1.0.6", "dev": true, @@ -2529,11 +2462,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/geojson": { - "version": "7946.0.10", - "dev": true, - "license": "MIT" - }, "node_modules/@types/hoist-non-react-statics": { "version": "3.3.1", "license": "MIT", @@ -2570,11 +2498,6 @@ "version": "15.7.13", "license": "MIT" }, - "node_modules/@types/qs": { - "version": "6.9.7", - "dev": true, - "license": "MIT" - }, "node_modules/@types/quill": { "version": "1.3.10", "license": "MIT", @@ -2599,14 +2522,6 @@ "csstype": "^3.0.2" } }, - "node_modules/@types/react-beautiful-dnd": { - "version": "13.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-dom": { "version": "18.3.5", "devOptional": true, @@ -2639,41 +2554,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-portal": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-scroll": { - "version": "1.8.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-simple-maps": { - "version": "3.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/d3-geo": "^2", - "@types/d3-zoom": "^2", - "@types/geojson": "*", - "@types/react": "*" - } - }, - "node_modules/@types/react-syntax-highlighter": { - "version": "15.5.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-transition-group": { "version": "4.4.11", "license": "MIT", @@ -3465,7 +3345,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.3", + "version": "4.25.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", + "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", "funding": [ { "type": "opencollective", @@ -3480,12 +3362,11 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001733", + "electron-to-chromium": "^1.5.199", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -3604,7 +3485,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001690", + "version": "1.0.30001734", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz", + "integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==", "funding": [ { "type": "opencollective", @@ -3618,8 +3501,7 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/canvg": { "version": "3.0.11", @@ -4501,8 +4383,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.76", - "license": "ISC" + "version": "1.5.200", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", + "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -11004,7 +10887,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -11019,10 +10904,9 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/ui/package.json b/ui/package.json index a9519eea..82a3e532 100644 --- a/ui/package.json +++ b/ui/package.json @@ -20,7 +20,6 @@ "@babel/standalone": "^7.28.0", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", - "@monaco-editor/react": "^4.6.0", "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^8.0.0", "@dnd-kit/utilities": "^3.2.2", @@ -30,6 +29,7 @@ "@fullcalendar/react": "^6.1.8", "@fullcalendar/timegrid": "^6.1.8", "@marsidev/react-turnstile": "^0.2.1", + "@monaco-editor/react": "^4.6.0", "@tanstack/react-query": "^4.29.19", "@tanstack/react-table": "^8.8.5", "axios": "^1.7.9", @@ -68,30 +68,24 @@ "yup": "^1.6.1" }, "devDependencies": { - "@types/babel__standalone": "^7.1.9", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@tailwindcss/typography": "^0.5.15", - "@types/d3-fetch": "^3.0.2", - "@types/d3-scale": "^4.0.3", + "@types/babel__standalone": "^7.1.9", "@types/file-saver": "^2.0.7", "@types/lodash": "^4.14.191", "@types/node": "^18.15.5", - "@types/qs": "^6.9.7", "@types/react": "^18.3.18", - "@types/react-beautiful-dnd": "^13.1.4", "@types/react-dom": "^18.3.5", "@types/react-helmet": "^6.1.9", "@types/react-highlight-words": "^0.16.4", "@types/react-modal": "^3.13.1", - "@types/react-portal": "^4.0.4", - "@types/react-scroll": "^1.8.7", - "@types/react-simple-maps": "^3.0.6", - "@types/react-syntax-highlighter": "^15.5.6", "@types/redux-state-sync": "^3.1.9", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.14", + "browserslist": "^4.25.2", + "caniuse-lite": "^1.0.30001734", "cross-env": "^7.0.3", "cssnano": "^6.0.1", "dotenv": "^16.0.3", diff --git a/ui/src/components/codeLayout/CodeEditor.tsx b/ui/src/components/codeLayout/CodeEditor.tsx index 0d974f11..29ab7ac5 100644 --- a/ui/src/components/codeLayout/CodeEditor.tsx +++ b/ui/src/components/codeLayout/CodeEditor.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect, useRef } from 'react' import Editor from '@monaco-editor/react' -import * as Icons from 'lucide-react' import { ComponentDefinition } from '../../@types/componentInfo' import { generateSingleComponentJSX, generateUniqueId } from '@/utils/codeParser' +import { Check, Code, Loader, MousePointer, Save, Settings, X } from 'lucide-react' interface CodeEditorProps { code: string @@ -427,9 +427,9 @@ export const CodeEditor: React.FC = ({ className="px-3 py-2 bg-gray-700 text-gray-300 rounded-lg text-xs font-medium hover:bg-gray-600 transition-colors flex items-center gap-2 disabled:opacity-50" > {isFormatting ? ( - + ) : ( - + )} Formatla @@ -442,7 +442,7 @@ export const CodeEditor: React.FC = ({ : 'bg-gray-700 text-gray-300 hover:bg-gray-600' }`} > - + Ayarlar @@ -450,7 +450,7 @@ export const CodeEditor: React.FC = ({ onClick={handleResetChanges} className="px-3 py-2 bg-red-600 text-white rounded-lg text-xs font-medium hover:bg-red-700 transition-colors flex items-center gap-2" > - + Sıfırla @@ -458,7 +458,7 @@ export const CodeEditor: React.FC = ({ onClick={handleApplyChanges} className="px-3 py-2 bg-green-600 text-white rounded-lg text-xs font-medium hover:bg-green-700 transition-colors flex items-center gap-2" > - + Uygula @@ -467,7 +467,7 @@ export const CodeEditor: React.FC = ({ onClick={onComponentSave} className="flex items-center gap-2 bg-yellow-600 text-white px-4 py-2 rounded-lg hover:bg-yellow-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm" > - + Kaydet @@ -622,12 +622,12 @@ export const CodeEditor: React.FC = ({ {hasChanges && ● Kaydedilmemiş değişiklikler} {showSuccessMessage && ( - + )} {isDragOver && ( - + Bileşeni bırakmaya hazır )} diff --git a/ui/src/components/codeLayout/ComponentLibrary.tsx b/ui/src/components/codeLayout/ComponentLibrary.tsx index cd309efb..c44e8185 100644 --- a/ui/src/components/codeLayout/ComponentLibrary.tsx +++ b/ui/src/components/codeLayout/ComponentLibrary.tsx @@ -1,5 +1,5 @@ import React, { useMemo, useState } from "react"; -import { Search } from "lucide-react"; +import { Search, Square } from "lucide-react"; import * as Icons from "lucide-react"; import { ComponentDefinition, HookInfo, PropertyInfo } from "../../@types/componentInfo"; import { getAllComponentDefinitions } from "./data/componentDefinitions"; @@ -88,7 +88,7 @@ export const ComponentLibrary: React.FC = ({ const getIcon = (iconName: string) => { const IconComponent = (Icons as any)[iconName]; - return IconComponent || Icons.Square; + return IconComponent || Square; }; return ( diff --git a/ui/src/views/AccessDenied.tsx b/ui/src/views/AccessDenied.tsx index 5ccdef74..ef048744 100644 --- a/ui/src/views/AccessDenied.tsx +++ b/ui/src/views/AccessDenied.tsx @@ -12,7 +12,7 @@ const AccessDenied = () => { return ( -
+
= ({ opacity: isDragging ? 0.5 : 1, } - const getIcon = (iconName: string) => { - const IconComponent = (Icons as any)[iconName] - return IconComponent ? : - } - const [isExpanded, setIsExpanded] = useState(true) const [isModalOpen, setIsModalOpen] = useState(false) const [formData, setFormData] = useState>({ @@ -147,10 +142,10 @@ export const MenuItemComponent: React.FC = ({ {isDesignMode && (
)} @@ -169,7 +164,7 @@ export const MenuItemComponent: React.FC = ({ {translate('::' + item.displayName)} - {item.url && } + {item.url && }
diff --git a/ui/src/views/menu/MenuManager.tsx b/ui/src/views/menu/MenuManager.tsx index 21500cdc..6dcb4c6f 100644 --- a/ui/src/views/menu/MenuManager.tsx +++ b/ui/src/views/menu/MenuManager.tsx @@ -1,8 +1,8 @@ import React, { useState } from 'react' -import * as Icons from 'lucide-react' import { SortableMenuTree } from './SortableMenuTree' import { MenuItem } from '@/@types/menu' import { useMenuData } from '@/utils/hooks/useMenuData' +import { AlertCircle, Loader2, Menu, Save } from 'lucide-react' export const MenuManager = () => { const { menuItems, setMenuItems, loading, error, refetch, saveMenuData } = useMenuData() @@ -48,7 +48,7 @@ export const MenuManager = () => { return (
- + Loading menu configuration...
@@ -60,7 +60,7 @@ export const MenuManager = () => {
- +

Error Loading Menu

{error}

@@ -82,7 +82,7 @@ export const MenuManager = () => {
{/* Sol kısım: Başlık */}
- +

Menu Manager

({menuItems.length} root items)
@@ -123,12 +123,12 @@ export const MenuManager = () => { > {isSaving ? ( <> - + Saving... ) : ( <> - + Save Changes )} @@ -146,7 +146,7 @@ export const MenuManager = () => { /> ) : (
- +

No menu items found

Try refreshing the page or contact your administrator

diff --git a/ui/vite.config.ts b/ui/vite.config.ts index 86fecb7a..fa31d3dd 100644 --- a/ui/vite.config.ts +++ b/ui/vite.config.ts @@ -19,7 +19,7 @@ export default defineConfig({ enabled: true, }, workbox: { - maximumFileSizeToCacheInBytes: 10000000, + maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, // 10 MB sınır }, manifest: { name: 'Platform', @@ -61,7 +61,7 @@ export default defineConfig({ host: '0.0.0.0', port: 80, open: false, - allowedHosts: ['dev.sozsoft.com', 'sozsoft.com', 'localhost', 'demo.sozsoft.com'], + allowedHosts: ['localhost', 'sozsoft.com', 'dev.sozsoft.com', 'demo.sozsoft.com'], }, define: { 'process.env': {},