diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 6423c5a84..4bff5fe46 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -17,14 +17,5 @@ jobs: with: dotnet-version: 10.0.x - - name: Setup NodeJS - uses: actions/setup-node@v4 - - - name: Restore TypeScript dependencies - run: | - cd src/MasterData.Web - npm install - cd ../../.. - - name: Build run: dotnet build diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml index 2a10e6980..7a474f2bf 100644 --- a/.github/workflows/nuget.yml +++ b/.github/workflows/nuget.yml @@ -14,9 +14,6 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: 10.0.x - - - name: Setup NodeJS - uses: actions/setup-node@v4 - name: Restore NuGet packages run: | @@ -28,6 +25,7 @@ jobs: strategy: matrix: project: + - src/MasterData.Storage.Abstractions - src/MasterData.Commons - src/MasterData.Core - src/MasterData.Web @@ -40,15 +38,15 @@ jobs: - uses: actions/checkout@v4 - name: Build and publish NuGet package run: | - npm install --prefix src/MasterData.Web cd ${{ matrix.project }} - BASE_VERSION=$(dotnet msbuild -nologo -getProperty:Version | tail -n 1 | tr -d '\r') + BASE_VERSION=$(dotnet msbuild -nologo -getProperty:VersionPrefix | tail -n 1 | tr -d '\r') + PREVIEW_SUFFIX=$(dotnet msbuild -nologo -getProperty:PreviewVersionSuffix | tail -n 1 | tr -d '\r') if [ "${GITHUB_REF_NAME}" = "rc" ]; then - PACKAGE_VERSION="${BASE_VERSION}-preview" + PACKAGE_VERSION="${BASE_VERSION}-${PREVIEW_SUFFIX}" else PACKAGE_VERSION="${BASE_VERSION}" fi - dotnet build -c release -p:PackageVersion="${PACKAGE_VERSION}" - dotnet pack -c release --no-build --output="nuget" -p:PackageVersion="${PACKAGE_VERSION}" + dotnet build -c release -p:Version="${PACKAGE_VERSION}" -p:PackageVersion="${PACKAGE_VERSION}" -p:InformationalVersion="${PACKAGE_VERSION}" + dotnet pack -c release --no-build --output="nuget" -p:Version="${PACKAGE_VERSION}" -p:PackageVersion="${PACKAGE_VERSION}" -p:InformationalVersion="${PACKAGE_VERSION}" cd nuget dotnet nuget push "*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/AGENTS.md b/AGENTS.md index 7904661c7..066df9282 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,9 +14,6 @@ JJMasterData is a .NET library and web UI for generating dynamic CRUDs from data ## Build - Install .NET SDK -- Install Node.js for `MasterData.Web` assets. -- Restore web assets: - - `npm install --prefix src/MasterData.Web` - Build from repo root: - `dotnet build` diff --git a/Directory.Build.props b/Directory.Build.props index 489e7f59c..4c5f5a4cd 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,10 +3,15 @@ https://www.github.com/JJConsulting/JJMasterData https://www.github.com/JJConsulting/JJMasterData JJMasterData.png - 4.5.37 + 5.0.0 + 8 + rc.$(PreviewNumber) + $(VersionPrefix) + $(VersionPrefix)-$(VersionSuffix) $(Version) - $(Version) - $(Version) + $(VersionPrefix) + $(VersionPrefix) + $(Version) README.NuGet.md true true diff --git a/Directory.Packages.props b/Directory.Packages.props index 9e3d10543..a37cf007f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,46 +3,48 @@ true - + + - - - + + + + - - - + + + - - - - - - - + + + + + + + - - + + - + - - - - - + + + + + - + - + \ No newline at end of file diff --git a/JJMasterData.slnx b/JJMasterData.slnx index 5bedf9d82..c2e1acdf0 100644 --- a/JJMasterData.slnx +++ b/JJMasterData.slnx @@ -13,7 +13,6 @@ - diff --git a/README.md b/README.md index 8a432dca6..52a570531 100644 --- a/README.md +++ b/README.md @@ -50,15 +50,14 @@ https://github.com/JJConsulting/JJMasterData/assets/28662273/9b874c9d-2a2f-4d3b- ```shell dotnet add package JJMasterData.Web ``` -3. Configure your `IConfiguration` source with a connection string at `JJMasterData:ConnectionString` and a secret key at `JJMasterData:SecretKey` +3. Configure your `IConfiguration` source with a connection string at `JJMasterData:ConnectionString` ```json { "JJMasterData": { "DataDictionaryTableName": "MasterData", "ConnectionString": "Server=localhost;Database=JJMasterData;Integrated Security=True;Trust Server Certificate=true", "ReadProcedurePattern": "{tablename}Get", - "WriteProcedurePattern": "{tablename}Set", - "SecretKey": "ExampleSecretKey" + "WriteProcedurePattern": "{tablename}Set" } } ``` @@ -78,7 +77,6 @@ var app = builder.Build(); //Required middlewares app.UseStaticFiles(); -app.UseSession(); //Session is very important app.MapDataDictionary(); app.MapMasterData(); @@ -109,11 +107,7 @@ See all steps in [documentation](https://md.jjconsulting.tech/articles/getting_s 5. Set the `WebEntryPoint` as startup project -6. At `src/Web` run at your terminal -```bash -npm i -``` -7. Run the project +6. Run the project ## Special Thanks #### Code contributors diff --git a/doc/MasterData.Docs/MasterData.Docs.csproj b/doc/MasterData.Docs/MasterData.Docs.csproj index bb4645869..3f6fc7fa6 100644 --- a/doc/MasterData.Docs/MasterData.Docs.csproj +++ b/doc/MasterData.Docs/MasterData.Docs.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net10.0 13 JJMasterData.Documentation JJMasterData.Documentation diff --git a/doc/MasterData.Docs/articles/components/data_dictionary/file_component.md b/doc/MasterData.Docs/articles/components/data_dictionary/file_component.md index bfca998c7..5fbaf3c51 100644 --- a/doc/MasterData.Docs/articles/components/data_dictionary/file_component.md +++ b/doc/MasterData.Docs/articles/components/data_dictionary/file_component.md @@ -34,6 +34,3 @@ Clicking on "Manage File" will open a new tab, allowing you to attach the desire - **Export as Link**: This option will change the name of the attachment within the exported file when exporting through the grid. - **Allow Pasting Files**: Allows the content of the file to be pasted to perform the import, or just a part of the content. It is not necessary to insert the entire file. - -- **Show Upload Outside Modal**: If this option is enabled, there will be no "Manage Files" option, and the import field will be displayed alongside the information after clicking edit. - diff --git a/doc/MasterData.Docs/articles/configurations.md b/doc/MasterData.Docs/articles/configurations.md index b766c5416..e26b30ee6 100644 --- a/doc/MasterData.Docs/articles/configurations.md +++ b/doc/MasterData.Docs/articles/configurations.md @@ -5,7 +5,7 @@ There are three ways to configure an application:

-**1)** Add your configuration keys in appsettings.json. On .NET Framework you will need to add `IConfiguration` via `Microsoft.Extensions.Configuration` +**1)** Add your configuration keys in appsettings.json. > [!TIP] > To autocomplete with JJMasterData keys in your text editor, put this URL in the JSON Schema of your IDE. @@ -70,4 +70,3 @@ You can change any property from: [Read more](localization.md) about localization.
- diff --git a/doc/MasterData.Docs/articles/custom_rules.md b/doc/MasterData.Docs/articles/customizations.md similarity index 92% rename from doc/MasterData.Docs/articles/custom_rules.md rename to doc/MasterData.Docs/articles/customizations.md index 283ca6261..be5026bf9 100644 --- a/doc/MasterData.Docs/articles/custom_rules.md +++ b/doc/MasterData.Docs/articles/customizations.md @@ -1,4 +1,6 @@ -# Custom Rules +# Customizations + +If you are looking for declarative validations configured directly in the Data Dictionary UI, see [Rules](rules.md). There are three ways to customize MasterData @@ -82,7 +84,6 @@ IF (MyCustomLogic, you can use your @Parameters) ``` > [!WARNING] -> It is not a best practice write business rules at database, recommended only for simple validations. +> It is not a best practice write business rules as exceptions at the database, please use [Rules](rules.md). --- - diff --git a/doc/MasterData.Docs/articles/errors/connection_string.md b/doc/MasterData.Docs/articles/errors/connection_string.md index e0aae288a..6110ec9d6 100644 --- a/doc/MasterData.Docs/articles/errors/connection_string.md +++ b/doc/MasterData.Docs/articles/errors/connection_string.md @@ -4,7 +4,7 @@ This is probably the first error you can find setting up JJMasterData. You can easily solve it in different ways. -## ..NET 8+ +## .NET 10 Add a default connection string to appsettings.json. ```json { @@ -14,8 +14,8 @@ Add a default connection string to appsettings.json. } ``` -## .NET Framework 4.8 and .NET Standard 2.0 -Using any supported .NET version, you can set programmatically your connection string. +## Programmatic configuration +You can set your connection string programmatically. ```csharp builder.Services.AddJJMasterDataCore(new MasterDataCoreOptionsConfiguration() { diff --git a/doc/MasterData.Docs/articles/getting_started.md b/doc/MasterData.Docs/articles/getting_started.md index 262f85dfd..6d9014ccf 100644 --- a/doc/MasterData.Docs/articles/getting_started.md +++ b/doc/MasterData.Docs/articles/getting_started.md @@ -1,7 +1,6 @@ # Getting Started -This tutorial assumes you will use .NET 8+, for .NET Framework 4.8 support, -check our [documentation](miscellaneous/netframework.md). +This tutorial assumes you will use .NET 10. ## 1. Install JJMasterData.Web from NuGet ![JJMasterData Nuget](../media/NuGet.png) @@ -19,7 +18,6 @@ You can replace the appsettings.json url from [here]((https://raw.githubusercont { "AllowedHosts": "*", "JJMasterData": { - "SecretKey": "My secret key for cryptography", "ConnectionString": "data source=localhost,1433;initial catalog=JJMasterData;Integrated Security=True" } } @@ -33,9 +31,6 @@ Add the following lines to your Program.cs //This line will add JJMasterData required services. builder.Services.AddJJMasterDataWeb(); -//Required middleware for JJMasterData -app.UseSession(); - //Add these lines before specifing default route: // Admin routes to create CRUDs diff --git a/doc/MasterData.Docs/articles/miscellaneous/assemblies.md b/doc/MasterData.Docs/articles/miscellaneous/assemblies.md index a0f6fc177..38a32e339 100644 --- a/doc/MasterData.Docs/articles/miscellaneous/assemblies.md +++ b/doc/MasterData.Docs/articles/miscellaneous/assemblies.md @@ -7,21 +7,21 @@ JJMasterData dependency tree can be represented by the following diagram: ## Assemblies ### JJMasterData.Web -Target Frameworks: ..NET 8 +Target Framework: .NET 10
Razor Class Library with web graphical interfaces to manipulate and render your metadata. ### JJMasterData.WebApi -Target Framework: ..NET 8 +Target Framework: .NET 10
Restful API to consume your metadata at any front-end. ### JJMasterData.Core -Target Frameworks: ..NET 8, .NET Standard 2.0 and .NET Framework 4.8 +Target Framework: .NET 10
Library to access your metadata from .NET and/or render it at HTML components. ### JJMasterData.Commons -Target: .NET Standard 2.0 +Target Framework: .NET 10
-Utilities to all assemblies, like database access, l10n, logging and utils. \ No newline at end of file +Utilities to all assemblies, like database access, l10n, logging and utils. diff --git a/doc/MasterData.Docs/articles/miscellaneous/netframework.md b/doc/MasterData.Docs/articles/miscellaneous/netframework.md deleted file mode 100644 index 549208783..000000000 --- a/doc/MasterData.Docs/articles/miscellaneous/netframework.md +++ /dev/null @@ -1,13 +0,0 @@ -# .NET Framework Support - -JJMasterData supports legacy .NET Framework systems, including ASP.NET WebForms and MVC5. - -## Differences from ASP.NET Core - -- JJMasterData.Web is not supported, we recommend starting a [incremental migration](https://devblogs.microsoft.com/dotnet/incremental-asp-net-to-asp-net-core-migration/) -and use the DataDictionary Razor Class Library in a external website. -- At Global.asax, use AddJJMasterDataCore() instead of AddJJMasterDataWeb() -- You will need to include in your Template.master or _Layout.cshtml, all JJMasterData front-end dependencies, check `_MasterDataScripts` and `_MasterDataStylesheets` source code. -- You will need a custom DI container like SimpleInjector -- After these steps, simply instantiate your using or use the Render route in your external ..NET 8 website. -- You will need to handle your manually \ No newline at end of file diff --git a/doc/MasterData.Docs/articles/rules.md b/doc/MasterData.Docs/articles/rules.md new file mode 100644 index 000000000..1164e4fe2 --- /dev/null +++ b/doc/MasterData.Docs/articles/rules.md @@ -0,0 +1,193 @@ +# Rules + +Rules allow you to run custom scripts before `insert` and `update` operations in a `FormElement`. + +Use them when field-level validations are not enough, and you need to validate combinations of values, check data in the database, or apply custom business rules. + +## Where to configure + +In the Data Dictionary UI, open your element and go to the `Rules` tab. + +Each rule has: + +- **Name**: Friendly identification for the rule +- **Rule Type**: Script language used by the rule +- **Script**: The validation logic itself + +Currently supported languages: + +- `SQL` +- `JavaScript` + +## How errors work + +Rules must produce validation errors only when something is wrong. + +If a rule does not produce any error, the operation continues normally. + +## SQL rules + +SQL rules execute a query and interpret the returned rows as validation errors. + +### Result contract + +- Return **no rows**: validation succeeded +- Return **1 column**: general validation error +- Return **2 columns**: field error, where: + - first column = field name + - second column = error message +- Column names do not matter + +### Available parameters + +You can use form values as parameters with the syntax: + +```sql +{FieldName} +``` + +### SQL examples + +General error: + +```sql +if exists ( + select 1 + from Customer + where Document = {Document} + and Id <> isnull({Id}, 0) +) + select 'There is already another customer with this document.' +``` + +Field error: + +```sql +if exists ( + select 1 + from Customer + where Email = {Email} + and Id <> isnull({Id}, 0) +) + select 'Email', 'This email is already in use.' +``` + +Multiple errors: + +```sql +-- Validation: required +IF @Nome IS NULL OR LTRIM(RTRIM(@Nome)) = '' +BEGIN + SELECT 'Name', 'Name is required'; +END; + +-- Validation: minimum and maximum length +IF LEN(@Nome) < 2 OR LEN(@Nome) > 100 +BEGIN + SELECT 'Name must be between 2 and 100 characters'; +END; + +-- Validation: only letters and spaces (no numbers or special characters) +IF @Nome LIKE '%[^A-Za-zÀ-ÿ ]%' +BEGIN + SELECT 'Name', 'Name contains invalid characters'; +END; + +-- Validation: avoid multiple consecutive spaces +IF @Nome LIKE '% %' +BEGIN + SELECT 'Name', 'Name cannot contain consecutive spaces'; +END; + +-- Validation: blacklist (business rule example) +IF UPPER(@Nome) IN ('ADMIN', 'ROOT', 'SYSTEM') +BEGIN + SELECT 'Name', 'Name not allowed'; +END; + +-- Validation: avoid unrealistically short names +IF LEN(REPLACE(@Nome, ' ', '')) < 2 +BEGIN + SELECT 'Name', 'Invalid name'; +END; + +-- Specific validation (example business rule) +IF @Nome = 'Bola' +BEGIN + SELECT 'Name', 'Name blocked by internal rule'; +END; + +``` + +## JavaScript rules + +JavaScript rules run with [Jint](https://github.com/sebastienros/jint). +They are executed **server-side**, not in the browser. + +The script receives: + +- `values`: object containing form values +- `addError(message)`: adds a general error +- `addError(name, message)`: adds a field error + +### JavaScript examples + +General error: + +```javascript +if (!values.Name && !values.CompanyName) { + addError("Either Name or CompanyName must be filled."); +} +``` + +Field error: + +```javascript +if (!values.Email) { + addError("Email", "Email is required."); +} +``` + +Multiple errors: + +```javascript +if (!values.StartDate) { + addError("StartDate", "Start date is required."); +} + +if (!values.EndDate) { + addError("EndDate", "End date is required."); +} + +if (values.StartDate && values.EndDate && values.StartDate > values.EndDate) { + addError("EndDate", "End date must be greater than or equal to start date."); +} +``` + +Cross-field validation: + +```javascript +if (values.Type === "Company" && !values.Document) { + addError("Document", "Document is required for companies."); +} +``` + +## Choosing between SQL and JavaScript + +Use `SQL` when: + +- validation depends on database queries +- you want to reuse database-side logic +- you need to validate against existing persisted data + +Use `JavaScript` when: + +- validation depends only on current form values +- you want simpler cross-field logic +- you want a more expressive scripting syntax for conditional rules + +## Notes + +- Rule field names must match the dictionary field names when you add field errors +- General errors are shown as form-level validation messages +- Field errors are attached to the corresponding field when possible diff --git a/doc/MasterData.Docs/articles/toc.yml b/doc/MasterData.Docs/articles/toc.yml index b362b253f..b7c709240 100644 --- a/doc/MasterData.Docs/articles/toc.yml +++ b/doc/MasterData.Docs/articles/toc.yml @@ -48,8 +48,10 @@ href: actions/cancel_action.md - name: Back href: actions/back_action.md - - name: Custom Rules - href: custom_rules.md + - name: Customizations + href: customizations.md + - name: Rules + href: rules.md - name: TagHelpers href: taghelpers.md - name: Localization @@ -146,7 +148,5 @@ items: - name: Multiple Forms Support href: multiple_forms.md - - name: .NET Framework Support - href: miscellaneous/netframework.md - name: Assemblies href: miscellaneous/assemblies.md diff --git a/doc/MasterData.Docs/articles/tutorials/creating_data_dictionary.md b/doc/MasterData.Docs/articles/tutorials/creating_data_dictionary.md index 628dbf936..09291753d 100644 --- a/doc/MasterData.Docs/articles/tutorials/creating_data_dictionary.md +++ b/doc/MasterData.Docs/articles/tutorials/creating_data_dictionary.md @@ -108,9 +108,6 @@ With Alignment At Grid at Right: #### Export You can define whether or not the field will be exported. -#### Validade Request -On .NET Framework 4.8 systems, the field will validate dangerous values, like Html tags and SQL commands. - ## **Panels** Allows you to separate the dictionary fields into panels. But only for add, edit and view actions. @@ -149,6 +146,14 @@ The Actions field is divided into two, Grid and Toolbar. - Filter: Shows all filter options for searching items within the table. - Log: Records and displays the actions performed within the table, including adding, editing and deleting. +## Rules +Within the Rules tab you can create script-based validations executed before `insert` and `update`. + +- SQL rules can return rows representing validation errors +- JavaScript rules can call `addError(message)` or `addError(fieldName, message)` + +For the complete reference, see [Rules](../rules.md). + ## **API** Within this tab it will be possible to edit each verb responsible for http permissions within the REST API. - ApplyUseridOn: Name of the field where the user ID filter will be applied. diff --git a/doc/MasterData.Docs/articles/tutorials/data_file.md b/doc/MasterData.Docs/articles/tutorials/data_file.md index 5bcfe697e..86b081f16 100644 --- a/doc/MasterData.Docs/articles/tutorials/data_file.md +++ b/doc/MasterData.Docs/articles/tutorials/data_file.md @@ -51,7 +51,7 @@ Where we configure the maximum size in bytes allowed in the upload. The maximum ### What can you do If you want to increase the size of this field, you will need to change the setting **MaxRequestLength** -The default size is 4 MB for .NET Framework and 30MB for .NET Core. +The default size is 30 MB for ASP.NET Core. ## Why when enabling a MultipleFile property I cannot enable ExportAsLink? @@ -66,4 +66,4 @@ Unfortunately in this scenario you will have to create a field for each file. ## Como acessar o arquivo de fora do elemento em uma rota externa? -Utilize o endpoint `/MasterData/File/Index/{elementName}/{fieldName}/{id}?fileName=YourFileName.png` para recuperar seu arquivo. Onde {id} é sua chave primária, caso seja mais de um campo, utilize vírgula para separar os valores. \ No newline at end of file +Utilize o endpoint `/MasterData/File/Index/{elementName}/{fieldName}/{id}?fileName=YourFileName.png` para recuperar seu arquivo. Onde {id} é sua chave primária, caso seja mais de um campo, utilize vírgula para separar os valores. diff --git a/doc/MasterData.Docs/articles/tutorials/ui_options.md b/doc/MasterData.Docs/articles/tutorials/ui_options.md index bfa8417da..7f6071d28 100644 --- a/doc/MasterData.Docs/articles/tutorials/ui_options.md +++ b/doc/MasterData.Docs/articles/tutorials/ui_options.md @@ -41,7 +41,7 @@ When displaying multiple items from your table, you can keep their titles fixed ![HeaderFixedOFF.png](../../media/HeaderFixedOFF.png) ### **MaintainValuesOnLoad** -This option will ensure that your search through the filter is saved when reloading the page, whether searching for filters or configuration options. +This option will ensure that your search through the filter is saved in cookies when reloading the page, whether searching for filters or configuration options. ![MaintainValuesOnLoadON.png](../../media/MaintainValuesOnLoadON.png) diff --git a/doc/MasterData.Docs/themes/jjconsulting/public/main.css b/doc/MasterData.Docs/themes/jjconsulting/public/main.css index c8ce11d79..67dda0ac5 100644 --- a/doc/MasterData.Docs/themes/jjconsulting/public/main.css +++ b/doc/MasterData.Docs/themes/jjconsulting/public/main.css @@ -108,7 +108,7 @@ header { main.container-xxl, footer .container-xxl, .search-results.container-xxl { - max-width: 1500px; + max-width: 1800px; padding-left: 0.8rem; padding-right: 0.8rem; } diff --git a/doc/README.md b/doc/README.md index 5a6b431ff..fa59e1a22 100644 --- a/doc/README.md +++ b/doc/README.md @@ -3,7 +3,7 @@ We use docfx to build the documentation in markdown to learn more visit [DocFx Documetantion](https://dotnet.github.io/docfx/) ## Building from source -1. Install [.NET Framework 4.8] +1. Install [.NET 10 SDK](https://dotnet.microsoft.com/download) 2. Install [NodeJS](https://nodejs.org/en/download/) diff --git a/example/MasterData.WebEntryPoint/Program.cs b/example/MasterData.WebEntryPoint/Program.cs index 85f0227c9..b6b96eca2 100644 --- a/example/MasterData.WebEntryPoint/Program.cs +++ b/example/MasterData.WebEntryPoint/Program.cs @@ -50,7 +50,6 @@ } app.UseStaticFiles(); -app.UseSession(); app.UseHttpsRedirection(); app.UseRouting(); app.UseResponseCaching(); diff --git a/jjmasterdata.json b/jjmasterdata.json index f2c6f6210..ada4a96f7 100644 --- a/jjmasterdata.json +++ b/jjmasterdata.json @@ -23,9 +23,6 @@ "null" ] }, - "SupportNetFramework": { - "type": "boolean" - }, "EnableBundleAndMinification": { "type": "boolean" }, @@ -53,12 +50,6 @@ "null" ] }, - "MasterDataUrl": { - "type": [ - "string", - "null" - ] - }, "ExportationFolderPath": { "type": [ "string", @@ -99,32 +90,23 @@ "string", "null" ] - }, - "SecretKey": { - "type": [ - "string", - "null" - ] } }, "required": [ "LayoutPath", "ModalLayoutPath", "CustomBootstrapPath", - "SupportNetFramework", "EnableBundleAndMinification", "CustomScriptsPaths", "DataDictionaryTableName", "AuditLogTableName", - "MasterDataUrl", "ExportationFolderPath", "ConnectionString", "ConnectionProvider", "LocalizationTableName", "ReadProcedurePattern", - "WriteProcedurePattern", - "SecretKey" + "WriteProcedurePattern" ] } } -} \ No newline at end of file +} diff --git a/src/ConsoleApps/MasterData.CommandLine/Hosting/ConsoleRunner.cs b/src/ConsoleApps/MasterData.CommandLine/Hosting/ConsoleRunner.cs index 400442d73..5af15077d 100644 --- a/src/ConsoleApps/MasterData.CommandLine/Hosting/ConsoleRunner.cs +++ b/src/ConsoleApps/MasterData.CommandLine/Hosting/ConsoleRunner.cs @@ -9,8 +9,6 @@ namespace JJMasterData.CommandLine.Hosting; public sealed class ConsoleRunner(IAnsiConsole console) { - private const string SecretKey = "jjmasterdata-console-tool"; - public Task ImportAsync(MasterDataCommandSettings settings, CancellationToken cancellationToken) { return ExecuteAsync( @@ -68,7 +66,6 @@ private static IConfiguration BuildConfiguration(MasterDataCommandSettings setti { ["JJMasterData:ConnectionString"] = settings.Connection, ["JJMasterData:ConnectionProvider"] = nameof(DataAccessProvider.SqlServer), - ["JJMasterData:SecretKey"] = SecretKey, ["JJMasterData:DataDictionaryTableSchema"] = schema, ["JJMasterData:DataDictionaryTableName"] = table }; @@ -89,4 +86,4 @@ private static (string Schema, string Table) ParseTable(string? table) ? (parts[0], parts[1]) : ("dbo", parts[0]); } -} \ No newline at end of file +} diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/ExpressionsMigrationService.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/ExpressionsMigrationService.cs deleted file mode 100644 index e9408003f..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/ExpressionsMigrationService.cs +++ /dev/null @@ -1,166 +0,0 @@ -using JJMasterData.Commons.Util; -using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.DataDictionary.Repository.Abstractions; - -namespace JJMasterData.LegacyMetadataMigrator; - -public class ExpressionsMigrationService( - IDataDictionaryRepository dataDictionaryRepository) -{ - private IDataDictionaryRepository DataDictionaryRepository { get; } = dataDictionaryRepository; - - public void Migrate() - { - var start = DateTime.Now; - - var formElements = DataDictionaryRepository.GetFormElementListAsync().GetAwaiter().GetResult(); - - foreach (var formElement in formElements) - { - foreach (var field in formElement.Fields) - { - FixFieldExpressions(field); - } - - foreach (var panel in formElement.Panels) - { - FixPanelExpressions(panel); - } - - foreach (var action in formElement.Options.GridTableActions) - { - FixActionExpressions(action); - } - - foreach (var action in formElement.Options.GridToolbarActions) - { - FixActionExpressions(action); - } - - foreach (var action in formElement.Options.FormToolbarActions) - { - FixActionExpressions(action); - } - - DataDictionaryRepository.InsertOrReplace(formElement); - } - - Console.WriteLine("Process started: {0}", start); - Console.WriteLine("Process finished: {0}", DateTime.Now); - } - - private void FixFieldExpressions(FormElementField field) - { - var visibleExpressionBefore = field.VisibleExpression; - - field.VisibleExpression = FixQuotationMarks(visibleExpressionBefore); - - if (visibleExpressionBefore != field.VisibleExpression) - { - Console.WriteLine("{0} VisibleExpression Before: {1}", field.Name, - visibleExpressionBefore); - Console.WriteLine("{0} VisibleExpression After: {1}", field.Name, - field.VisibleExpression); - } - - var enableExpressionBefore = field.EnableExpression; - - field.EnableExpression = FixQuotationMarks(enableExpressionBefore); - - if (enableExpressionBefore != field.EnableExpression) - { - Console.WriteLine("{0} EnableExpression Before: {1}", field.Name, - enableExpressionBefore); - Console.WriteLine("{0} EnableExpression After: {1}", field.Name, field.EnableExpression); - } - - foreach (var action in field.Actions) - { - FixActionExpressions(action); - } - } - - // ReSharper disable once MemberCanBeMadeStatic.Local -#pragma warning disable CA1822 - private void FixPanelExpressions(FormElementPanel panel) -#pragma warning restore CA1822 - { - var visibleExpressionBefore = panel.VisibleExpression; - - panel.VisibleExpression = FixQuotationMarks(visibleExpressionBefore); - - if (visibleExpressionBefore != panel.VisibleExpression) - { - Console.WriteLine("Panel {0} VisibleExpression Before: {1}", panel.PanelId, - visibleExpressionBefore); - Console.WriteLine("Panel {0} VisibleExpression After: {1}", panel.PanelId, - panel.VisibleExpression); - } - - var enableExpressionBefore = panel.EnableExpression; - - panel.EnableExpression = FixQuotationMarks(enableExpressionBefore); - - if (enableExpressionBefore != panel.EnableExpression) - { - Console.WriteLine("Panel {0} EnableExpression Before: {1}", panel.PanelId, - enableExpressionBefore); - Console.WriteLine("Panel {0} EnableExpression After: {1}", panel.PanelId, - panel.EnableExpression); - } - } - - // ReSharper disable once MemberCanBeMadeStatic.Local -#pragma warning disable CA1822 - private void FixActionExpressions(BasicAction action) -#pragma warning restore CA1822 - { - var visibleExpressionBefore = action.VisibleExpression; - - action.VisibleExpression = FixQuotationMarks(visibleExpressionBefore); - - if (visibleExpressionBefore != action.VisibleExpression) - { - Console.WriteLine("Action {0} VisibleExpression Before: {1}", action.Name, - visibleExpressionBefore); - Console.WriteLine("Action {0} VisibleExpression After: {1}", action.Name, - action.VisibleExpression); - } - - var enableExpressionBefore = action.EnableExpression; - - action.EnableExpression = FixQuotationMarks(enableExpressionBefore); - - if (enableExpressionBefore != action.EnableExpression) - { - Console.WriteLine("Action {0} EnableExpression Before: {1}", action.Name, - enableExpressionBefore); - Console.WriteLine("Action {0} EnableExpression After: {1}", action.Name, - action.EnableExpression); - } - } - - private static string FixQuotationMarks(string? expression) - { - if (string.IsNullOrEmpty(expression)) - return "val:1"; - - var quotedValues = StringManager.FindValuesByInterval(expression, '\'','\'').ToList(); - var bracedValues = StringManager.FindValuesByInterval(expression, '{','}').ToList(); - - var newExpression = expression; - - foreach (var bracedValue in bracedValues) - { - var hasQuotes = quotedValues.Any(quotedValue => quotedValue.Contains(bracedValue)); - - if(hasQuotes) - continue; - - newExpression = expression.Replace($"{{{bracedValue}}}", $"'{{{bracedValue}}}'"); - } - - return newExpression; - } -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/GridActions.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/GridActions.cs deleted file mode 100644 index c59da8d9a..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/GridActions.cs +++ /dev/null @@ -1,260 +0,0 @@ -#nullable disable - -using JJMasterData.Core.DataDictionary.Models.Actions; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - - -public class GridActions -{ - [JsonProperty("editAction")] - public EditAction EditAction { get; set; } = new(); - - [JsonProperty("deleteAction")] - public DeleteAction DeleteAction { get; set; } = new(); - - [JsonProperty("viewAction")] - public ViewAction ViewAction { get; set; } = new(); - - [JsonProperty("commandActions")] - private List CommandActions { get; set; } = []; - - [JsonProperty("urlRedirectActions")] - private List UrlRedirectActions { get; set; } = []; - - [JsonProperty("internalActions")] - private List InternalActions { get; set; } = []; - - [JsonProperty("jsActions")] - private List JsActions { get; set; } = []; - - - public void Set(BasicAction action) - { - if (action is ViewAction viewAction) - { - ViewAction = viewAction; - } - else if (action is EditAction editAction) - { - EditAction = editAction; - } - else if (action is DeleteAction deleteAction) - { - DeleteAction = deleteAction; - } - else if (action is SqlCommandAction cmdAction) - { - for (int i = 0; i < CommandActions.Count; i++) - { - if (CommandActions[i].Name.Equals(action.Name)) - { - CommandActions[i] = cmdAction; - return; - } - } - CommandActions.Add(cmdAction); - } - else if (action is UrlRedirectAction urlAction) - { - for(int i =0;i< UrlRedirectActions.Count; i++) - { - if (UrlRedirectActions[i].Name.Equals(action.Name)) - { - UrlRedirectActions[i] = urlAction; - return; - } - } - UrlRedirectActions.Add(urlAction); - } - else if (action is InternalAction internalAction) - { - for (int i = 0; i < InternalActions.Count; i++) - { - if (InternalActions[i].Name.Equals(action.Name)) - { - InternalActions[i] = internalAction; - return; - } - } - InternalActions.Add(internalAction); - } - else if (action is ScriptAction jsAction) - { - for (int i = 0; i < JsActions.Count; i++) - { - if (JsActions[i].Name.Equals(action.Name)) - { - JsActions[i] = jsAction; - return; - } - } - JsActions.Add(jsAction); - } - else - { - throw new ArgumentException("Invalid Action"); - } - } - - public void Add(SqlCommandAction action) - { - ValidateAction(action); - CommandActions.Add(action); - } - - - public void Add(UrlRedirectAction action) - { - ValidateAction(action); - UrlRedirectActions.Add(action); - } - - public void Add(InternalAction action) - { - ValidateAction(action); - InternalActions.Add(action); - } - - public void Add(ScriptAction action) - { - ValidateAction(action); - JsActions.Add(action); - } - - public void Remove(SqlCommandAction action) - { - ValidateAction(action); - CommandActions.Remove(action); - } - public void Remove(UrlRedirectAction action) - { - ValidateAction(action); - UrlRedirectActions.Remove(action); - } - - public void Remove(InternalAction action) - { - ValidateAction(action); - InternalActions.Remove(action); - } - - public void Remove(ScriptAction action) - { - ValidateAction(action); - JsActions.Remove(action); - } - - - public void Remove(BasicAction action) - { - if (action is SqlCommandAction acSql) - { - Remove(acSql); - } - else if (action is UrlRedirectAction acUrl) - { - Remove(acUrl); - } - else if (action is InternalAction acInternal) - { - Remove(acInternal); - } - else if (action is ScriptAction acJs) - { - Remove(acJs); - } - else - { - throw new ArgumentException("Invalid Action"); - } - } - - public void Remove(string actionName) - { - BasicAction action = Get(actionName); - Remove(action); - } - -#pragma warning disable CA1822 - // ReSharper disable once MemberCanBeMadeStatic.Local - private void ValidateAction(BasicAction action) -#pragma warning restore CA1822 - { - if (action == null) - throw new ArgumentNullException(nameof(action)); - - if (string.IsNullOrEmpty(action.Name)) - throw new ArgumentException("Property name action is not valid"); - } - - public BasicAction Get(string name) - { - BasicAction action = null; - if (ViewAction.Name.Equals(name)) - return ViewAction; - - if (EditAction.Name.Equals(name)) - return EditAction; - - if (DeleteAction.Name.Equals(name)) - return DeleteAction; - - action = CommandActions.Find(x => x.Name.Equals(name)); - if (action != null) - return action; - - action = UrlRedirectActions.Find(x => x.Name.Equals(name)); - if (action != null) - return action; - - action = InternalActions.Find(x => x.Name.Equals(name)); - if (action != null) - return action; - - action = JsActions.Find(x => x.Name.Equals(name)); - if (action != null) - return action; - - return null; - } - - public void SetDefault(string actionName) - { - foreach (var action in GetAll()) - { - action.IsDefaultOption = action.Name.Equals(actionName); - } - } - - public List GetAll() - { - var listAction = new List(); - - if (ViewAction is not null) - listAction.Add(ViewAction); - - if (EditAction is not null) - listAction.Add(EditAction); - - if (DeleteAction is not null) - listAction.Add(DeleteAction); - - if (CommandActions is { Count: > 0 }) - listAction.AddRange(CommandActions.ToArray()); - - if (UrlRedirectActions is { Count: > 0 }) - listAction.AddRange(UrlRedirectActions.ToArray()); - - if (InternalActions is { Count: > 0 }) - listAction.AddRange(InternalActions.ToArray()); - - if (JsActions is { Count: > 0 }) - listAction.AddRange(JsActions.ToArray()); - - return listAction.OrderBy(x => x.Order).ToList(); - } - - public int Count => GetAll().FindAll(x => x.IsVisible).Count; -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/GridToolbarActions.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/GridToolbarActions.cs deleted file mode 100644 index 7fe8cd2f9..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/GridToolbarActions.cs +++ /dev/null @@ -1,311 +0,0 @@ -#nullable disable - -using JJMasterData.Core.DataDictionary.Models.Actions; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - -public class GridToolbarActions -{ - [JsonProperty("insertAction")] - public InsertAction InsertAction { get; set; } = new(); - - [JsonProperty("legendAction")] - public LegendAction LegendAction { get; set; } = new(); - - [JsonProperty("refreshAction")] - public RefreshAction RefreshAction { get; set; } = new(); - - [JsonProperty("filterAction")] - public FilterAction FilterAction { get; set; } = new(); - - [JsonProperty("importAction")] - public ImportAction ImportAction { get; set; } = new(); - - [JsonProperty("exportAction")] - public ExportAction ExportAction { get; set; } = new(); - - [JsonProperty("configAction")] - public ConfigAction ConfigAction { get; set; } = new(); - - [JsonProperty("sortAction")] - public SortAction SortAction { get; set; } = new(); - - [JsonProperty("logAction")] - public AuditLogGridToolbarAction AuditLogGridToolbarAction { get; set; } = new(); - - [JsonProperty("commandActions")] - private List CommandActions { get; set; } = []; - - [JsonProperty("urlRedirectActions")] - private List UrlRedirectActions { get; set; } = []; - - [JsonProperty("internalActions")] - private List InternalActions { get; set; } = []; - - [JsonProperty("jsActions")] - private List JsActions { get; set; } = []; - - - public void Set(BasicAction action) - { - switch (action) - { - case InsertAction insertAction: - InsertAction = insertAction; - break; - case LegendAction legendAction: - LegendAction = legendAction; - break; - case RefreshAction refreshAction: - RefreshAction = refreshAction; - break; - case FilterAction filterAction: - FilterAction = filterAction; - break; - case ImportAction importAction: - ImportAction = importAction; - break; - case ExportAction exportAction: - ExportAction = exportAction; - break; - case ConfigAction configAction: - ConfigAction = configAction; - break; - case SortAction sortAction: - SortAction = sortAction; - break; - case AuditLogGridToolbarAction logAction: - AuditLogGridToolbarAction = logAction; - break; - case SqlCommandAction cmdAction: - { - for (int i = 0; i < CommandActions.Count; i++) - { - if (CommandActions[i].Name.Equals(action.Name)) - { - CommandActions[i] = cmdAction; - return; - } - } - CommandActions.Add(cmdAction); - break; - } - case UrlRedirectAction urlAction: - { - for (int i = 0; i < UrlRedirectActions.Count; i++) - { - if (UrlRedirectActions[i].Name.Equals(action.Name)) - { - UrlRedirectActions[i] = urlAction; - return; - } - } - UrlRedirectActions.Add(urlAction); - break; - } - case InternalAction internalAction: - { - for (int i = 0; i < InternalActions.Count; i++) - { - if (InternalActions[i].Name.Equals(action.Name)) - { - InternalActions[i] = internalAction; - return; - } - } - InternalActions.Add(internalAction); - break; - } - case ScriptAction scriptAction: - { - for (int i = 0; i < JsActions.Count; i++) - { - if (JsActions[i].Name.Equals(action.Name)) - { - JsActions[i] = scriptAction; - return; - } - } - JsActions.Add(scriptAction); - break; - } - default: - throw new ArgumentException("Invalid Action"); - } - } - - - public void Add(SqlCommandAction action) - { - ValidateAction(action); - CommandActions.Add(action); - } - - public void Add(UrlRedirectAction action) - { - ValidateAction(action); - UrlRedirectActions.Add(action); - } - - public void Add(InternalAction action) - { - ValidateAction(action); - InternalActions.Add(action); - } - - public void Add(ScriptAction action) - { - ValidateAction(action); - JsActions.Add(action); - } - - public void Add(BasicAction action) - { - if (action is SqlCommandAction cmdAction) - Add(cmdAction); - else if (action is UrlRedirectAction urlAction) - Add(urlAction); - else if (action is InternalAction internalAction) - Add(internalAction); - else if (action is ScriptAction scriptAction) - Add(scriptAction); - else - throw new ArgumentException("Invalid Action"); - } - - public void Remove(SqlCommandAction action) - { - ValidateAction(action); - CommandActions.Remove(action); - } - public void Remove(UrlRedirectAction action) - { - ValidateAction(action); - UrlRedirectActions.Remove(action); - } - - public void Remove(InternalAction action) - { - ValidateAction(action); - InternalActions.Remove(action); - } - public void Remove(ScriptAction action) - { - ValidateAction(action); - JsActions.Remove(action); - } - - public void Remove(BasicAction action) - { - if (action is SqlCommandAction acSql) - { - Remove(acSql); - } - else if (action is UrlRedirectAction acUrl) - { - Remove(acUrl); - } - else if (action is InternalAction acInternal) - { - Remove(acInternal); - } - else if (action is ScriptAction jScriptAction) - { - Remove(jScriptAction); - } - else - { - throw new ArgumentException("Invalid Action"); - } - } - - public void Remove(string actionName) - { - BasicAction action = Get(actionName); - Remove(action); - } - -#pragma warning disable CA1822 - // ReSharper disable once MemberCanBeMadeStatic.Local - private void ValidateAction(BasicAction action) -#pragma warning restore CA1822 - { - if (action == null) - throw new ArgumentNullException(nameof(action)); - - if (string.IsNullOrEmpty(action.Name)) - throw new ArgumentException("Property name action is not valid"); - } - - public BasicAction Get(string name) - { - return GetAll().Find(x => x.Name.Equals(name)); - } - - - public List GetAll() - { - var actionList = new List(); - - if (InsertAction is not null) - { - } - else - { - InsertAction = new InsertAction(); - } - - actionList.Add(InsertAction); - - if (LegendAction is not null) - { - } - else - { - LegendAction = new LegendAction(); - } - - actionList.Add(LegendAction); - - RefreshAction ??= new RefreshAction(); - - actionList.Add(RefreshAction); - - FilterAction ??= new FilterAction(); - - actionList.Add(FilterAction); - - ImportAction ??= new ImportAction(); - - actionList.Add(ImportAction); - - ExportAction ??= new ExportAction(); - - actionList.Add(ExportAction); - - ConfigAction ??= new ConfigAction(); - - actionList.Add(ConfigAction); - - SortAction ??= new SortAction(); - - actionList.Add(SortAction); - - AuditLogGridToolbarAction ??= new AuditLogGridToolbarAction(); - - actionList.Add(AuditLogGridToolbarAction); - if (CommandActions is { Count: > 0 }) - actionList.AddRange(CommandActions.ToArray()); - - if (UrlRedirectActions is { Count: > 0 }) - actionList.AddRange(UrlRedirectActions.ToArray()); - - if (InternalActions is { Count: > 0 }) - actionList.AddRange(InternalActions.ToArray()); - - if (JsActions is { Count: > 0 }) - actionList.AddRange(JsActions.ToArray()); - return actionList.OrderBy(x => x.Order).ToList(); - } -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/Metadata.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/Metadata.cs deleted file mode 100644 index 67d0bee45..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/Metadata.cs +++ /dev/null @@ -1,101 +0,0 @@ -#nullable disable - -using System.Collections; -using JJMasterData.Commons.Data.Entity.Models; -using JJMasterData.Core.DataDictionary.Models; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - -[JsonObject("elementInfo")] -public class Metadata -{ - [JsonProperty("table")] - public Element Table { get; set; } - - [JsonProperty("form")] - public MetadataForm Form { get; set; } - - [JsonProperty("uioptions")] - public MetadataOptions Options { get; set; } - - [JsonProperty("api")] - public MetadataApiOptions ApiOptions { get; set; } - - public static explicit operator FormElement(Metadata metadata) => metadata.GetFormElement(); - - public FormElement GetFormElement() - { - var formElement = new FormElement(Table) - { - Title = Form.Title, - SubTitle = Form.SubTitle, - Panels = Form.Panels, - Info = Table.Info, - Indexes = Table.Indexes, - EnableSynchronism = Table.EnableSynchronism, - SynchronismMode = Table.SynchronismMode, - }; - - foreach (var item in Form.FormFields) - { - var field = formElement.Fields[item.Name]; - field.Component = item.Component; - field.VisibleExpression = item.VisibleExpression; - field.EnableExpression = item.EnableExpression; - field.TriggerExpression = item.TriggerExpression; - field.LineGroup = item.LineGroup; - field.CssClass = item.CssClass; - field.HelpDescription = item.HelpDescription; - field.DataItem = item.DataItem; - field.Attributes[FormElementField.MinValueAttribute] = item.MinValue; - field.Attributes[FormElementField.MaxValueAttribute] = item.MaxValue; - field.DataFile = item.DataFile; - field.Export = item.Export; - field.ValidateRequest = item.ValidateRequest ?? true; - field.AutoPostBack = item.AutoPostBack; - field.NumberOfDecimalPlaces = item.NumberOfDecimalPlaces; - field.Actions = item.Actions; - field.Attributes = item.Attributes?.Cast() - .ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value) ?? new Dictionary(); - field.PanelId = item.PanelId; - field.InternalNotes = item.InternalNotes; - } - - - formElement.Options = new FormElementOptions - { - Form = Options.Form, - Grid = Options.Grid - }; - - formElement.Options.GridTableActions.Clear(); - - foreach (var a in Options.GridActions.GetAll()) - { - formElement.Options.GridTableActions.Add(a); - } - - formElement.Options.GridToolbarActions.Clear(); - - foreach (var a in Options.ToolbarActions.GetAll()) - { - formElement.Options.GridToolbarActions.Add(a); - } - - formElement.ApiOptions = new FormElementApiOptions - { - JsonFormatting = ApiOptions.FormatType, - EnableAdd = ApiOptions.EnableAdd, - EnableGetAll = ApiOptions.EnableGetAll, - EnableDel = ApiOptions.EnableDel, - EnableUpdate = ApiOptions.EnableUpdate, - EnableGetDetail = ApiOptions.EnableGetDetail, - EnableUpdatePart = ApiOptions.EnableUpdatePart, - ApplyUserIdOn = ApiOptions.ApplyUserIdOn - }; - - return formElement; - } - -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataApiOptions.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataApiOptions.cs deleted file mode 100644 index 50ec645c7..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataApiOptions.cs +++ /dev/null @@ -1,78 +0,0 @@ -#nullable disable - -using System.Runtime.Serialization; -using JJMasterData.Core.DataDictionary.Models; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - -[DataContract] -public class MetadataApiOptions -{ - /// - /// Get all records. Verb GET - /// - [JsonProperty("enableGetAll")] - public bool EnableGetAll { get; set; } - - /// - /// Get a record detail. Verb GET - /// - [JsonProperty("enableGetDetail")] - public bool EnableGetDetail { get; set; } - - /// - /// Add new records. Verb POST - /// - [JsonProperty("enableAdd")] - public bool EnableAdd { get; set; } - - /// - /// Update records. Verb PUT - /// - [JsonProperty("enableUpdate")] - public bool EnableUpdate { get; set; } - - /// - /// Update some especifics fields. Verb PATCH - /// - [JsonProperty("enableUpdatePart")] - public bool EnableUpdatePart { get; set; } - - /// - /// Delete a record. Verb DEL - /// - [JsonProperty("enableDel")] - public bool EnableDel { get; set; } - - /// - /// Json Format - /// - [JsonProperty("formatType")] - public ApiJsonFormatting FormatType { get; set; } = ApiJsonFormatting.Lowercase; - - /// - /// Aways apply UserId (from login) as filter or on set - /// - [JsonProperty("applyUserIdOn")] - public string ApplyUserIdOn { get; set; } - - - /// - /// Format the field according to the dictionary parameterization - /// - public string GetFieldNameParsed(string fieldName) - { - return FormatType == ApiJsonFormatting.Lowercase ? fieldName.ToLower() : fieldName; - } - - - public bool HasSetMehtod() - { - return EnableAdd || - EnableUpdate || - EnableUpdatePart || - EnableDel; - } - -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataForm.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataForm.cs deleted file mode 100644 index cb16bca43..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataForm.cs +++ /dev/null @@ -1,23 +0,0 @@ -#nullable disable - -using System.Runtime.Serialization; -using JJMasterData.Core.DataDictionary.Models; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - -[DataContract] -public class MetadataForm -{ - [JsonProperty("formfields")] - public List FormFields { get; set; } = []; - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("subtitle")] - public string SubTitle { get; set; } - - [JsonProperty("panels")] - public List Panels { get; set; } = []; -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataFormField.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataFormField.cs deleted file mode 100644 index 02221833f..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataFormField.cs +++ /dev/null @@ -1,75 +0,0 @@ -#nullable disable - -using System.Collections; -using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataDictionary.Models.Actions; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - - -public class MetadataFormField -{ - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("component")] - public FormComponent Component { get; set; } - - [JsonProperty("visibleexpression")] - public string VisibleExpression { get; set; } - - [JsonProperty("enableexpression")] - public string EnableExpression { get; set; } - - [JsonProperty("triggerexpression")] - public string TriggerExpression { get; set; } - - [JsonProperty("order")] - public int Order { get; set; } - - [JsonProperty("linegroup")] - public int LineGroup { get; set; } - - [JsonProperty("cssclass")] - public string CssClass { get; set; } - - [JsonProperty("helpdescription")] - public string HelpDescription { get; set; } - - [JsonProperty("dataitem")] - public FormElementDataItem DataItem { get; set; } - - [JsonProperty("datafile")] - public FormElementDataFile DataFile { get; set; } - - [JsonProperty("export")] - public bool Export { get; set; } - - [JsonProperty("validaterequest")] - public bool? ValidateRequest { get; set; } - - [JsonProperty("autopostback")] - public bool AutoPostBack { get; set; } - - [JsonProperty("maxvalue")] - public float? MaxValue { get; set; } - - [JsonProperty("minvalue")] - public float? MinValue { get; set; } - - [JsonProperty("numberdecimalplaces")] - public int NumberOfDecimalPlaces { get; set; } - - [JsonProperty("actions")] - public FormElementFieldActionList Actions { get; set; } - - [JsonProperty("attributes")] - public Hashtable Attributes { get; set; } - - [JsonProperty("panelid")] - public int PanelId { get; set; } - - [JsonProperty("internalnotes")] - public string InternalNotes { get; set; } -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataInfo.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataInfo.cs deleted file mode 100644 index fa2ca232c..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -#nullable disable -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - -public class MetadataInfo -{ - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("tablename")] - public string TableName { get; set; } - - [JsonProperty("info")] - public string Info { get; set; } - - [JsonProperty("sync")] - public string Sync { get; set; } - - [JsonProperty("modified")] - public DateTime Modified { get; set; } - - public MetadataInfo() - { - - } - - public MetadataInfo(Metadata metadata, DateTime modified) - { - Name = metadata.Table.Name; - TableName = metadata.Table.TableName; - Info = metadata.Table.Info; - Sync = metadata.Table.EnableSynchronism ? "1" : "0"; - Modified = modified; - } - -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataOptions.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataOptions.cs deleted file mode 100644 index 65688e4c9..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigration/MetadataOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -#nullable disable -using JJMasterData.Core.DataDictionary.Models; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator.FormElementMigration; - - -public class MetadataOptions -{ - [JsonProperty("grid")] - public GridUI Grid { get; set; } = new(); - - [JsonProperty("form")] - public FormUI Form { get; set; } = new(); - - [JsonProperty("toolBarActions")] - public GridToolbarActions ToolbarActions { get; set; } = new(); - - [JsonProperty("gridActions")] - public GridActions GridActions { get; set; } = new(); -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigrationService.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigrationService.cs deleted file mode 100644 index 7c24d7bf5..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/FormElementMigrationService.cs +++ /dev/null @@ -1,121 +0,0 @@ -using JJMasterData.Commons.Configuration.Options; -using JJMasterData.Commons.Data; -using JJMasterData.Commons.Exceptions; -using JJMasterData.Core.Configuration.Options; -using JJMasterData.Core.DataDictionary.Repository.Abstractions; -using Microsoft.Extensions.Options; - -namespace JJMasterData.LegacyMetadataMigrator; - -public class FormElementMigrationService(IDataDictionaryRepository dataDictionaryRepository, - MetadataRepository metadataRepository, - IOptions commonsOptions, - IOptions options, - ExpressionsMigrationService expressionsMigrationService) -{ - private DataAccess? _dataAccess; - private IDataDictionaryRepository DataDictionaryRepository { get; } = dataDictionaryRepository; - private MetadataRepository MetadataRepository { get; } = metadataRepository; - private ExpressionsMigrationService ExpressionsMigrationService { get; } = expressionsMigrationService; - - private DataAccess DataAccess - { - get - { - if (_dataAccess == null) - { - var connStr = commonsOptions.Value.ConnectionString; - var connProvider = commonsOptions.Value.ConnectionProvider; - - if (connStr == null) - throw new DataAccessException("Connection string not found"); - - _dataAccess = new(connStr, connProvider); - } - - return _dataAccess; - } - } - - private string TableName => Options.DataDictionaryTableName; - private MasterDataCoreOptions Options { get; } = options.Value; - - public void Migrate() - { - var start = DateTime.Now; - - var containsLegacyType = DataAccess.GetResult($"SELECT [type] from {TableName} where [type] <> 'F'"); - - if (containsLegacyType is null) - { - Console.WriteLine("✅ DataDictionary is already migrated"); - return; - } - - var databaseDictionaries = MetadataRepository.GetMetadataList(); - - DataAccess.SetCommand($"DROP TABLE {TableName}"); - // DataAccess.SetCommand($"DROP PROCEDURE {Options.GetReadProcedureName(TableName)}"); - // DataAccess.SetCommand($"DROP PROCEDURE {Options.GetWriteProcedureName(TableName)}"); - - DataDictionaryRepository.CreateStructureIfNotExistsAsync().GetAwaiter().GetResult(); - - Console.WriteLine("\u2705 Re-created {0} and all related stored procedures", TableName); - - foreach (var metadata in databaseDictionaries) - { - var formElement = metadata.GetFormElement(); - - formElement.UseReadProcedure = true; - formElement.UseWriteProcedure = true; - - foreach (var field in formElement.Fields) - { - if (field.DataFile is not null) - { - field.DataFile.MaxFileSize /= 1000000; - } - } - - DataDictionaryRepository.InsertOrReplaceAsync(formElement).GetAwaiter().GetResult(); - Console.WriteLine("\u2705 {0}", formElement.Name); - } - - DataAccess.SetCommand($"delete from {TableName} where type <> 'F'"); - - DataAccess.SetCommand($$""" - UPDATE {{TableName}} - SET [json] = REPLACE([json], - '{search_id}', - '{SearchId}') - WHERE [json] LIKE '%{search_id}%'; - """); - - Console.WriteLine("✅ Replaced {{search_id}} to {{SearchId}} in all elements"); - - DataAccess.SetCommand($$""" - UPDATE {{TableName}} - SET [json] = REPLACE([json], - '{search_text}', - '{SearchText}') - WHERE [json] LIKE '%{search_text}%'; - """); - - Console.WriteLine("✅ Replaced {{search_text}} to {{SearchText}} in all elements"); - - DataAccess.SetCommand($$""" - UPDATE {{TableName}} - SET [json] = REPLACE([json], - '{objname}', - '{FieldName}') - WHERE [json] LIKE '%{objname}%'; - """); - - Console.WriteLine("✅ Replaced {{objname}} to {{FieldName}} in all elements"); - - Console.WriteLine($"Process started: {start}"); - Console.WriteLine($"Process finished: {DateTime.Now}"); - - ExpressionsMigrationService.Migrate(); - } -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/MasterData.LegacyMetadataMigrator.csproj b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/MasterData.LegacyMetadataMigrator.csproj deleted file mode 100644 index e72049fdb..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/MasterData.LegacyMetadataMigrator.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - JJMasterData.LegacyMetadataMigrator - JJMasterData.LegacyMetadataMigrator - - - - - - - - - - - diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/MetadataRepository.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/MetadataRepository.cs deleted file mode 100644 index 7296a64bd..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/MetadataRepository.cs +++ /dev/null @@ -1,173 +0,0 @@ -#nullable disable - -using JJMasterData.Commons.Data.Entity.Models; -using JJMasterData.Commons.Data.Entity.Repository; -using JJMasterData.Commons.Data.Entity.Repository.Abstractions; -using JJMasterData.Core.Configuration.Options; -using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.DataDictionary.Repository.Abstractions; -using JJMasterData.Core.DataDictionary.Structure; -using JJMasterData.LegacyMetadataMigrator.FormElementMigration; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; - -namespace JJMasterData.LegacyMetadataMigrator; - -public class MetadataRepository(IEntityRepository entityRepository, IOptions options) -{ - private Element _masterDataElement; - - internal Element MasterDataElement - { - get - { - if (_masterDataElement == null) - { - var tableName = options.Value.DataDictionaryTableName; - _masterDataElement = DataDictionaryStructure.GetElement("dbo", tableName); - } - return _masterDataElement; - } - } - - /// - public IEnumerable GetMetadataList(bool? sync = null) - { - var list = new List(); - var entityParameters = new EntityParameters(); - entityParameters.OrderBy.AddOrReplace("name", OrderByDirection.Asc); - entityParameters.OrderBy.AddOrReplace("type", OrderByDirection.Asc); - if (sync.HasValue) - entityParameters.Filters.Add("sync", (bool)sync ? "1" : "0"); - - MasterDataElement.Fields.Add(new ElementField - { - Name = "namefilter", - Filter = new ElementFilter(FilterMode.Contain), - DataBehavior = FieldBehavior.ViewOnly - }); - - //Ignore procedures to apply compatibility - MasterDataElement.UseReadProcedure = false; - MasterDataElement.UseWriteProcedure = false; - - string currentName = ""; - var dt = entityRepository.GetDictionaryListResultAsync(MasterDataElement,entityParameters, false).GetAwaiter().GetResult(); - Metadata currentParser = null; - foreach (var row in dt.Data) - { - string name = row["name"].ToString(); - if (!currentName.Equals(name)) - { - ApplyCompatibility(currentParser); - - currentName = name; - list.Add(new Metadata()); - currentParser = list[^1]; - } - - string json = row["json"].ToString(); - var type = row["type"].ToString()!; - switch (type) - { - case "T": - currentParser!.Table = JsonConvert.DeserializeObject(json); - break; - case "F": - currentParser!.Form = JsonConvert.DeserializeObject(json, new JsonSerializerSettings - { - Error = (sender, args) => - { - args.ErrorContext.Handled = true; - } - }); - break; - case "L": - currentParser!.Options = JsonConvert.DeserializeObject(json); - break; - case "A": - currentParser!.ApiOptions = JsonConvert.DeserializeObject(json); - break; - } - } - - ApplyCompatibility(currentParser); - - return list; - } - - - public static void ApplyCompatibility(Metadata dicParser) - { - if (dicParser?.Table == null) - return; - - //Nairobi - dicParser.Options ??= new MetadataOptions(); - - dicParser.Options.ToolbarActions ??= new GridToolbarActions(); - - dicParser.Options.GridActions ??= new GridActions(); - - - //Denver - if (dicParser.ApiOptions == null) - { - dicParser.ApiOptions = new MetadataApiOptions(); - if (dicParser.Table.EnableSynchronism) - { - dicParser.ApiOptions.EnableGetAll = true; - dicParser.ApiOptions.EnableGetDetail = true; - dicParser.ApiOptions.EnableAdd = true; - dicParser.ApiOptions.EnableUpdate = true; - dicParser.ApiOptions.EnableUpdatePart = true; - dicParser.ApiOptions.EnableDel = true; - } - } - - if (string.IsNullOrEmpty(dicParser.Table.TableName)) - { - dicParser.Table.TableName = dicParser.Table.Name; - } - - //Tokio - if (dicParser.Form is { Panels: null }) dicParser.Form.Panels = []; - - //Professor - if (dicParser.Form != null) - { - foreach (var field in dicParser.Form.FormFields) - { - if (field.DataItem is not { DataItemType: DataItemType.Manual }) - continue; - - if (field.DataItem.Command != null && !string.IsNullOrEmpty(field.DataItem.Command.Sql)) - field.DataItem.DataItemType = DataItemType.SqlCommand; - else if (field.DataItem.ElementMap != null && !string.IsNullOrEmpty(field.DataItem.ElementMap.ElementName)) - field.DataItem.DataItemType = DataItemType.ElementMap; - } - } - - //Arturito - // foreach (var action in dicParser.Options.GridActions.GetAll() - // .Where(action => action is UrlRedirectAction or InternalAction or ScriptAction or SqlCommandAction)) - // { - // //action.IsUserCreated = true; - // } - // - // foreach (var action in dicParser.Options.ToolbarActions - // .GetAll() - // .Where(action => action is UrlRedirectAction or InternalAction or ScriptAction or SqlCommandAction)) - // { - // //action.IsUserCreated = true; - // } - - - //Sirius - - dicParser.Options.ToolbarActions.ExportAction.ProcessOptions ??= new ProcessOptions(); - - dicParser.Options.ToolbarActions.ImportAction.ProcessOptions ??= new ProcessOptions(); - } -} \ No newline at end of file diff --git a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/Program.cs b/src/ConsoleApps/MasterData.LegacyMetadataMigrator/Program.cs deleted file mode 100644 index 759bb5798..000000000 --- a/src/ConsoleApps/MasterData.LegacyMetadataMigrator/Program.cs +++ /dev/null @@ -1,20 +0,0 @@ -using JJMasterData.Core.Configuration; -using JJMasterData.LegacyMetadataMigrator; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -var services = new ServiceCollection(); -var configurationBuilder = new ConfigurationBuilder(); -configurationBuilder.AddJsonFile("appsettings.json"); -services.AddJJMasterDataCore(); - -services.AddSingleton(configurationBuilder.Build()); -services.AddTransient(); -services.AddTransient(); -services.AddTransient(); - -var serviceProvider = services.BuildServiceProvider(); - -var service = serviceProvider.GetRequiredService(); - -service.Migrate(); \ No newline at end of file diff --git a/src/MasterData.Commons/Configuration/MasterDataServiceBuilder.cs b/src/MasterData.Commons/Configuration/MasterDataServiceBuilder.cs index 69ccb697f..c99732c64 100644 --- a/src/MasterData.Commons/Configuration/MasterDataServiceBuilder.cs +++ b/src/MasterData.Commons/Configuration/MasterDataServiceBuilder.cs @@ -10,7 +10,7 @@ namespace JJMasterData.Commons.Configuration; -public class MasterDataServiceBuilder(IServiceCollection services) +public class MasterDataServiceBuilder(IServiceCollection services) { public IServiceCollection Services { get; } = services; @@ -66,8 +66,7 @@ public MasterDataServiceBuilder WithEntityRepository() where T : IEntityRepos return this; } - public MasterDataServiceBuilder WithEntityRepository( - Func implementationFactory) + public MasterDataServiceBuilder WithEntityRepository(Func implementationFactory) { Services.Replace(ServiceDescriptor.Transient(implementationFactory)); return this; diff --git a/src/MasterData.Commons/Configuration/Options/MasterDataCommonsOptions.cs b/src/MasterData.Commons/Configuration/Options/MasterDataCommonsOptions.cs index 9ba14eca1..d0b425d9d 100644 --- a/src/MasterData.Commons/Configuration/Options/MasterDataCommonsOptions.cs +++ b/src/MasterData.Commons/Configuration/Options/MasterDataCommonsOptions.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Runtime.InteropServices; using System.Text.Json.Serialization; using JJMasterData.Commons.Data; using JJMasterData.Commons.Data.Entity.Models; @@ -16,7 +15,6 @@ namespace JJMasterData.Commons.Configuration.Options; /// /// JJMasterData key/value configurations. /// They're populated from JJMasterData section on , following its implementations. -/// On .NET Framework, add an builder to your application. /// public sealed class MasterDataCommonsOptions { @@ -47,15 +45,6 @@ public sealed class MasterDataCommonsOptions [Display(Name = "Write Procedure Pattern")] public string WriteProcedurePattern { get; set; } = "{tablename}Set"; - /// - /// Secret key used at JJMasterDataEncryptionService - /// - [Display(Name = "Cryptography Secret Key")] - public string? SecretKey { get; set; } - - [JsonIgnore] - public static bool IsNetFramework { get; } = RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework"); - internal ConnectionString GetConnectionString(Guid? guid) { if (guid is null) @@ -131,4 +120,4 @@ public static string RemoveTbPrefix(string tableName) return tableName; } -} \ No newline at end of file +} diff --git a/src/MasterData.Commons/Configuration/ServiceCollectionExtensions.cs b/src/MasterData.Commons/Configuration/ServiceCollectionExtensions.cs index 9412f9678..f78954513 100644 --- a/src/MasterData.Commons/Configuration/ServiceCollectionExtensions.cs +++ b/src/MasterData.Commons/Configuration/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Configuration.Options; using JJMasterData.Commons.Data; using JJMasterData.Commons.Data.Entity.Providers; @@ -6,78 +7,89 @@ using JJMasterData.Commons.Data.Entity.Repository.Abstractions; using JJMasterData.Commons.Security.Cryptography; using JJMasterData.Commons.Security.Cryptography.Abstractions; +using JJMasterData.Commons.Security; +using JJMasterData.Commons.Storage; using JJMasterData.Commons.Tasks; using JJMasterData.Commons.Util; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Localization; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace JJMasterData.Commons.Configuration; public static class ServiceCollectionExtensions { - public static MasterDataServiceBuilder AddJJMasterDataCommons(this IServiceCollection services) + extension(IServiceCollection services) { - var builder = new MasterDataServiceBuilder(services); + public MasterDataServiceBuilder AddJJMasterDataCommons() + { + var builder = new MasterDataServiceBuilder(services); - services.AddMasterDataCommonsServices(); + services.AddMasterDataCommonsServices(); - return builder; - } + return builder; + } - public static MasterDataServiceBuilder AddJJMasterDataCommons(this IServiceCollection services, - IConfiguration configuration) - { - var builder = new MasterDataServiceBuilder(services); + public MasterDataServiceBuilder AddJJMasterDataCommons(IConfiguration configuration) + { + var builder = new MasterDataServiceBuilder(services); - builder.Services.Configure(configuration.GetJJMasterData()); + builder.Services.Configure(configuration.GetJJMasterData()); - services.AddMasterDataCommonsServices(); + services.AddMasterDataCommonsServices(); - return builder; - } + return builder; + } - public static MasterDataServiceBuilder AddJJMasterDataCommons(this IServiceCollection services, - Action configure) - { - var builder = new MasterDataServiceBuilder(services); + public MasterDataServiceBuilder AddJJMasterDataCommons(Action configure) + { + var builder = new MasterDataServiceBuilder(services); - services.AddMasterDataCommonsServices(); - if (configure != null) - services.PostConfigure(configure); + services.AddMasterDataCommonsServices(); + if (configure != null) + services.PostConfigure(configure); - return builder; - } - - private static void AddMasterDataCommonsServices(this IServiceCollection services) - { - services.AddOptions() - .BindConfiguration("JJMasterData") - .Validate(o => !string.IsNullOrEmpty(o.ConnectionString), - "Connection string is required at JJMasterData:ConnectionString at your configuration source.") - .Validate(o => !string.IsNullOrEmpty(o.SecretKey), - "Secret key is required at JJMasterData:SecretKey at your configuration source.") - .ValidateOnStart(); - - services.AddScoped(); + return builder; + } - services.AddOptions().BindConfiguration("JJMasterData"); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + private void AddMasterDataCommonsServices() + { + services.AddOptions() + .BindConfiguration("JJMasterData") + .Validate(o => !string.IsNullOrEmpty(o.ConnectionString), + "Connection string is required at JJMasterData:ConnectionString at your configuration source.") + .ValidateOnStart(); -#pragma warning disable CS0618 // Type or member is obsolete - services.AddTransient(); -#pragma warning restore CS0618 // Type or member is obsolete - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddTransient(); - services.AddTransient(); + services.TryAddTransient(); + + services.AddOptions() + .BindConfiguration("HmacOptions") + .Configure((options, configuration) => + { + if (string.IsNullOrWhiteSpace(options.SecretKey)) + options.SecretKey = configuration["JJMasterData:SecretKey"] ?? string.Empty; + }); + + services.TryAddScoped(); - services.AddSingleton(); - - services.AddScoped(); + services.AddDataProtection(); + + services.AddOptions().BindConfiguration("JJMasterData"); + + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + + services.TryAddTransient(); + + services.TryAddTransient(); + + services.TryAddTransient(); + services.TryAddSingleton(); + } } -} \ No newline at end of file +} diff --git a/src/MasterData.Commons/Data/DataAccessAsync.cs b/src/MasterData.Commons/Data/DataAccessAsync.cs index 9371d5508..21605ccc2 100644 --- a/src/MasterData.Commons/Data/DataAccessAsync.cs +++ b/src/MasterData.Commons/Data/DataAccessAsync.cs @@ -72,12 +72,12 @@ private async Task ExecuteDataCommandAsync( { try { - using var dbCommand = CreateDbCommand(command); + await using var dbCommand = CreateDbCommand(command); dbCommand.Connection = await CreateConnectionAsync(cancellationToken); - using (dbCommand.Connection) + await using (dbCommand.Connection) { - using (var reader = await dbCommand.ExecuteReaderAsync(cancellationToken)) + await using (var reader = await dbCommand.ExecuteReaderAsync(cancellationToken)) { await readerAction(reader, state, cancellationToken); @@ -103,9 +103,9 @@ private async Task ExecuteDataCommandAsync( object? scalarResult; try { - using var dbCommand = CreateDbCommand(command); + await using var dbCommand = CreateDbCommand(command); dbCommand.Connection = await CreateConnectionAsync(cancellationToken); - using (dbCommand.Connection) + await using (dbCommand.Connection) { scalarResult = await dbCommand.ExecuteScalarAsync(cancellationToken); @@ -126,9 +126,9 @@ public async Task SetCommandAsync(DataAccessCommand command, CancellationTo int rowsAffected; try { - using var dbCommand = CreateDbCommand(command); + await using var dbCommand = CreateDbCommand(command); dbCommand.Connection = await CreateConnectionAsync(cancellationToken); - using (dbCommand.Connection) + await using (dbCommand.Connection) { rowsAffected = await dbCommand.ExecuteNonQueryAsync(cancellationToken); @@ -150,37 +150,25 @@ public async Task SetCommandListAsync(IEnumerable comman int numberOfRowsAffected = 0; DataAccessCommand? currentCommand = null; - using var connection = await CreateConnectionAsync(cancellationToken); + await using var connection = await CreateConnectionAsync(cancellationToken); -#if NET48 - using var transaction = connection.BeginTransaction(); -#else - using var transaction = await connection.BeginTransactionAsync(cancellationToken); -#endif + await using var transaction = await connection.BeginTransactionAsync(cancellationToken); try { foreach (var command in commands) { currentCommand = command; - using var dbCommand = CreateDbCommand(command); + await using var dbCommand = CreateDbCommand(command); dbCommand.Connection = connection; dbCommand.Transaction = transaction; numberOfRowsAffected += await dbCommand.ExecuteNonQueryAsync(cancellationToken); } -#if NET48 - transaction.Commit(); -#else await transaction.CommitAsync(cancellationToken); -#endif } catch (Exception ex) { -#if NET48 - transaction.Rollback(); -#else await transaction.RollbackAsync(cancellationToken); -#endif throw GetDataAccessException(ex, currentCommand); } @@ -234,13 +222,13 @@ private async Task GetDataAsync( { try { - using var dbCommand = CreateDbCommand(command); + await using var dbCommand = CreateDbCommand(command); dbCommand.Connection = await CreateConnectionAsync(cancellationToken); - using (dbCommand.Connection) + await using (dbCommand.Connection) { - using (var dataReader = - await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow, cancellationToken)) + await using (var dataReader = + await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow, cancellationToken)) { while (await dataReader.ReadAsync(cancellationToken)) { @@ -273,11 +261,11 @@ await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow, cancellationToken) try { - using var dbCommand = CreateDbCommand(command); + await using var dbCommand = CreateDbCommand(command); dbCommand.Connection = await CreateConnectionAsync(cancellationToken); - using var connection = dbCommand.Connection; - using (var dataReader = await dbCommand.ExecuteReaderAsync(cancellationToken)) + await using var connection = dbCommand.Connection; + await using (var dataReader = await dbCommand.ExecuteReaderAsync(cancellationToken)) { List columnNames = []; @@ -342,7 +330,7 @@ public async Task TryConnectionAsync(CancellationToken cancell { if (connection.State == ConnectionState.Open) { - connection.Close(); + await connection.CloseAsync(); } connection.Dispose(); @@ -397,4 +385,4 @@ public async Task ExecuteBatchAsync(string script, int? timeoutSeconds = n return true; } -} \ No newline at end of file +} diff --git a/src/MasterData.Commons/Data/DataAccessProviderHelper.cs b/src/MasterData.Commons/Data/DataAccessProviderHelper.cs index 716fcf602..cc7e4fcb5 100644 --- a/src/MasterData.Commons/Data/DataAccessProviderHelper.cs +++ b/src/MasterData.Commons/Data/DataAccessProviderHelper.cs @@ -33,8 +33,7 @@ public static DataAccessProvider GetDataAccessProviderFromString(string provider "Oracle.ManagedDataAccess.Core.Client" => DataAccessProvider.OracleNetCore, "MySql" => DataAccessProvider.MySql, "MySql.Data.MySqlClient.MySqlClientFactory" => DataAccessProvider.MySql, - "PostgreSql" => DataAccessProvider.PostgreSql, - "Npgsql.NpgsqlFactory" => DataAccessProvider.PostgreSql, + "PostgreSql" or "Npgsql.NpgsqlFactory" => DataAccessProvider.PostgreSql, _ => throw new DataAccessProviderException("Unknown data access provider name.") }; } diff --git a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerAlterTableScripts.cs b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerAlterTableScripts.cs index e1b477529..f22746c35 100644 --- a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerAlterTableScripts.cs +++ b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerAlterTableScripts.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; using System.Linq; +using System.Text; using JetBrains.Annotations; using JJMasterData.Commons.Data.Entity.Models; namespace JJMasterData.Commons.Data.Entity.Providers; -public class SqlServerAlterTableScripts : SqlServerScriptsBase +public static class SqlServerAlterTableScripts { [CanBeNull] public static string GetAlterTableScript(Element element, IEnumerable fields) @@ -13,21 +14,26 @@ public static string GetAlterTableScript(Element element, IEnumerable relationships) { @@ -21,7 +21,7 @@ public static string GetCreateTableScript(Element element, List 0) @@ -50,7 +50,7 @@ public static string GetCreateTableScript(Element element, List 0) { sql.AppendLine(", "); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("CONSTRAINT [PK_"); sql.Append(element.TableName); sql.Append("] PRIMARY KEY NONCLUSTERED ("); @@ -79,21 +79,21 @@ public static string GetCreateTableScript(Element element, List 0) sql.AppendLine(", "); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append(index.Columns[i]); } sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine(")"); sql.AppendLine("GO"); counter++; @@ -143,7 +143,7 @@ private static string GetRelationshipsScript(Element element, List options, IOptionsSnapshot sqlServerOptions) - : SqlServerScriptsBase { public string GetReadProcedureScript(Element element) { @@ -34,13 +32,15 @@ public string GetReadProcedureScript(Element element) } else { - sql.AppendLine(GetSqlDropIfExists(procedureName)); + sql.Append(SqlServerScriptsHelper.GetSqlDropIfExists(procedureName)); + sql.AppendLine(); sql.Append("CREATE PROCEDURE "); } sql.AppendLine(procedureName); sql.AppendLine("@orderby VARCHAR(MAX), "); - sql.AppendLine(GetParameters(fields, addMasterDataParameters: true)); + sql.Append(GetParameters(fields, addMasterDataParameters: true)); + sql.AppendLine(); sql.AppendLine("AS "); sql.AppendLine("BEGIN "); sql.Append(GetReadScript(element, fields)); @@ -49,41 +49,41 @@ public string GetReadProcedureScript(Element element) return sql.ToString(); } - internal string GetReadScript(Element element, List fields) + internal StringBuilder GetReadScript(Element element, List fields) { var sql = new StringBuilder(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @sqlColumn NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @sqlTable NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @sqlWhere NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @sqlOrderBy NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @sqlOffset NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @query NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); if (fields.Exists(f => f.Filter.Type is FilterMode.MultValuesContain or FilterMode.MultValuesEqual)) { sql.AppendLine("DECLARE @sqlLikeIn NVARCHAR(MAX)"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); } sql.AppendLine("DECLARE @count INT"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--COLUMNS"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlColumn = '"); var index = 1; foreach (var field in fields) { - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.Append(""); if (field.DataBehavior == FieldBehavior.ViewOnly) { @@ -104,20 +104,20 @@ internal string GetReadScript(Element element, List fields) index++; } - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine(" '"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--TABLES"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("SET @sqlTable = 'FROM "); - sql.Append(GetTableName(element)); + sql.Append(SqlServerScriptsHelper.GetTableName(element)); sql.AppendLine(" WITH (NOLOCK)'"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--CONDITIONALS"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlWhere = ' WHERE 1=1 '"); foreach (var field in fields) @@ -127,7 +127,7 @@ internal string GetReadScript(Element element, List fields) if (field.DataBehavior == FieldBehavior.ViewOnly) { sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("/*"); sql.Append("TODO: FILTER "); sql.AppendLine($"[{field.Name}]"); @@ -142,11 +142,11 @@ internal string GetReadScript(Element element, List fields) if (field.DataType is FieldType.Date or FieldType.DateTime or FieldType.DateTime2) { - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("IF @"); sql.Append(field.Name); sql.AppendLine("_from IS NOT NULL"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("SET @sqlWhere = @sqlWhere + ' AND CONVERT(DATE, "); sql.Append($"[{field.Name}]"); sql.Append(") BETWEEN CONVERT(VARCHAR(10), @"); @@ -157,11 +157,11 @@ internal string GetReadScript(Element element, List fields) } else { - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("IF @"); sql.Append(field.Name); sql.AppendLine("_from IS NOT NULL"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("SET @sqlWhere = @sqlWhere + ' AND "); sql.Append($"[{field.Name}]"); sql.Append(" BETWEEN @"); @@ -176,11 +176,11 @@ internal string GetReadScript(Element element, List fields) } case FilterMode.Contain: sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("IF @"); sql.Append(field.Name); sql.AppendLine(" IS NOT NULL"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("SET @sqlWhere = @sqlWhere + ' AND "); sql.Append($"[{field.Name}]"); sql.Append($" LIKE ''%'' + RTRIM(@{field.Name}) + ''%'' '"); @@ -196,11 +196,11 @@ internal string GetReadScript(Element element, List fields) if (field.Filter.Type == FilterMode.Equal || field.IsPk) { sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("IF @"); sql.Append(field.Name); sql.AppendLine(" IS NOT NULL"); - sql.Append(Tab,2); + sql.Append(SqlServerScriptsHelper.Tab,2); sql.Append("SET @sqlWhere = @sqlWhere + ' AND "); sql.Append($"[{field.Name}] = @{field.Name}'"); } @@ -214,14 +214,14 @@ internal string GetReadScript(Element element, List fields) if (field.DataBehavior != FieldBehavior.ViewOnly) continue; - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("*/"); } sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--ORDER BY"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); var listPk = fields.FindAll(x => x.IsPk); if (listPk.Count == 0) { @@ -236,154 +236,154 @@ internal string GetReadScript(Element element, List fields) sql.AppendLine("'"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("IF @orderby IS NOT NULL AND @orderby <> ''"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN"); - sql.Append(Tab); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOrderBy = ' ORDER BY ' + @orderby"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("END"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--PAGINATION"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("IF @pag < 1"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("SET @pag = 1"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = ' '"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + ' OFFSET ('"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + '(@pag - 1)'"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + ' * '"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + '@regporpag'"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + ') ROWS FETCH NEXT '"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + '@regporpag'"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @sqlOffset = @sqlOffset + ' ROWS ONLY '"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--TOTAL OF RECORDS"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("IF @qtdtotal is null or @qtdtotal = 0"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("SET @qtdtotal = 0;"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("SET @query = N'SELECT @count = COUNT(*) ' + @sqlTable + @sqlWhere"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("EXECUTE sp_executesql @query,"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("N'"); sql.Append(GetParameters(fields, addMasterDataParameters: false, tabLevel: 2)); sql.Append("@count int output',"); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append(GetFilterParametersScript(fields, tabCount: 2)); sql.Append("@count = @qtdtotal output"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("END"); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("--DATASET RESULT"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @query = N'SELECT ' + @sqlColumn + @sqlTable + @sqlWhere + @sqlOrderBy + @sqlOffset"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("EXECUTE sp_executesql @query,"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("N'"); sql.Append(GetParameters(fields, addMasterDataParameters: true, tabLevel: 1)); sql.Append('\''); sql.Append(','); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append(GetFilterParametersScript(fields)); sql.AppendLine("@regporpag,"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("@pag,"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("@qtdtotal"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine(); - return sql.ToString(); + return sql; } - private string GetMultValuesEquals(string fieldName) + private StringBuilder GetMultValuesEquals(string fieldName) { var sql = new StringBuilder(); if (sqlServerOptions.Value.CompatibilityLevel < 130) { sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("IF @"); sql.Append(fieldName); sql.AppendLine(" IS NOT NULL"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendFormat("SET @likein = ' AND {0} IN ('", fieldName); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendFormat("WHILE CHARINDEX(',', @{0}) <> 0", fieldName); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("BEGIN"); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.AppendFormat("SET @likein = @likein + CHAR(39) + SUBSTRING(@{0},1,CHARINDEX(',',@{0}) -1) + CHAR(39);", fieldName); sql.AppendLine(); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.AppendFormat("SET @{0} = RIGHT(@{0} , LEN(@{0}) - CHARINDEX(',', @{0}));", fieldName); sql.AppendLine(); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.AppendLine("SET @likein = @likein + ', ';"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("END"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendFormat("SET @likein = @likein + CHAR(39) + @{0} + CHAR(39) + ') '", fieldName); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("SET @sqlcond = @sqlcond + @likein"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("END"); } else { sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append($"IF @{fieldName} IS NOT NULL"); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("BEGIN"); sql.AppendLine(); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.Append($"SET @sqlWhere = @sqlWhere + ' AND [{fieldName}] IN (SELECT value FROM STRING_SPLIT(@{fieldName}, '',''))'"); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("END"); } - return sql.ToString(); + return sql; } - private static string GetFilterParametersScript(List fields, int tabCount = 1) + private static StringBuilder GetFilterParametersScript(List fields, int tabCount = 1) { var sql = new StringBuilder(); @@ -394,7 +394,7 @@ private static string GetFilterParametersScript(List fields, int t if (field.Filter.Type is FilterMode.Range) { sql.AppendLine($"@{field.Name}_from,"); - sql.Append(Tab, tabCount); + sql.Append(SqlServerScriptsHelper.Tab, tabCount); sql.AppendLine($"@{field.Name}_to,"); } else @@ -402,11 +402,11 @@ private static string GetFilterParametersScript(List fields, int t sql.AppendLine($"@{field.Name},"); } - sql.Append(Tab, tabCount); + sql.Append(SqlServerScriptsHelper.Tab, tabCount); } } - return sql.ToString(); + return sql; } private static bool IsFilter(ElementField field) @@ -414,7 +414,7 @@ private static bool IsFilter(ElementField field) return field.Filter.Type != FilterMode.None || field.IsPk; } - private static string GetParameters(List fields, bool addMasterDataParameters, int tabLevel = 0) + private static StringBuilder GetParameters(List fields, bool addMasterDataParameters, int tabLevel = 0) { var sql = new StringBuilder(); @@ -436,11 +436,11 @@ private static string GetParameters(List fields, bool addMasterDat { size = $"({field.Size},{field.NumberOfDecimalPlaces})"; } - sql.Append(Tab, tabLevel); + sql.Append(SqlServerScriptsHelper.Tab, tabLevel); sql.AppendLine($"@{field.Name}_from {typeName}{size},"); - sql.Append(Tab, tabLevel); + sql.Append(SqlServerScriptsHelper.Tab, tabLevel); sql.AppendLine($"@{field.Name}_to {typeName}{size},"); - sql.Append(Tab, tabLevel); + sql.Append(SqlServerScriptsHelper.Tab, tabLevel); break; } @@ -465,7 +465,7 @@ private static string GetParameters(List fields, bool addMasterDat sql.AppendLine(", "); } - sql.Append(Tab, tabLevel); + sql.Append(SqlServerScriptsHelper.Tab, tabLevel); } break; @@ -476,30 +476,30 @@ private static string GetParameters(List fields, bool addMasterDat if (addMasterDataParameters) { sql.AppendLine("@regporpag INT, "); - sql.Append(Tab, tabLevel); + sql.Append(SqlServerScriptsHelper.Tab, tabLevel); sql.AppendLine("@pag INT, "); - sql.Append(Tab, tabLevel); + sql.Append(SqlServerScriptsHelper.Tab, tabLevel); sql.Append("@qtdtotal INT OUTPUT "); } - return sql.ToString(); + return sql; } private string GetFilterMultValuesContains(string fieldName) { var sql = new StringBuilder(); sql.AppendLine(); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.Append("IF @"); sql.Append(fieldName); sql.AppendLine(" IS NOT NULL"); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN"); if (sqlServerOptions.Value.CompatibilityLevel >= 130) { - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("SET @sqlWhere = @sqlWhere + ' AND "); sql.Append($""" EXISTS ( @@ -511,33 +511,33 @@ WHERE [{fieldName}] LIKE ''%'' + s.value + ''%'' } else { - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("DECLARE @likein NVARCHAR(MAX)"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("SET @likein = ' AND ( '"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append($"WHILE CHARINDEX(',', @{fieldName}) <> 0"); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("BEGIN"); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.AppendFormat("SET @likein = @likein + '{0} LIKE ' + CHAR(39) + '%' + SUBSTRING(@{0}, 1, CHARINDEX(',', @{0}) -1) + '%' + CHAR(39);", fieldName); sql.AppendLine(); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.AppendFormat("SET @{0} = RIGHT(@{0} , LEN(@{0}) - CHARINDEX(',', @{0}));", fieldName); sql.AppendLine(); - sql.Append(Tab, 3); + sql.Append(SqlServerScriptsHelper.Tab, 3); sql.AppendLine("SET @likein = @likein + ' OR ';"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("END"); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendFormat("SET @likein = @likein + '{0} LIKE ' + CHAR(39) + '%' + @{0} + '%' + CHAR(39) + ' ) '", fieldName); sql.AppendLine(); - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.AppendLine("SET @sqlWhere = @sqlWhere + @likein"); } - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("END"); return sql.ToString(); diff --git a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScripts.cs b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScripts.cs index c7d5fa7d5..ac6ce5d4e 100644 --- a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScripts.cs +++ b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScripts.cs @@ -28,7 +28,7 @@ public string GetReadScript(Element element) { var fields = element.Fields.FindAll(f => f.DataBehavior is FieldBehavior.Real); - return readProcedureScripts.GetReadScript(element, fields); + return readProcedureScripts.GetReadScript(element, fields).ToString(); } public static string GetCreateTableScript(Element element, List relationships) diff --git a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScriptsBase.cs b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScriptsHelper.cs similarity index 82% rename from src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScriptsBase.cs rename to src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScriptsHelper.cs index c3edaa089..8e6f7c599 100644 --- a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScriptsBase.cs +++ b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerScriptsHelper.cs @@ -5,11 +5,11 @@ namespace JJMasterData.Commons.Data.Entity.Providers; -public abstract class SqlServerScriptsBase +internal static class SqlServerScriptsHelper { - protected const char Tab = '\t'; - - protected static string GetTableName(Element element) + public const char Tab = '\t'; + + public static string GetTableName(Element element) { var sql = new StringBuilder(); @@ -24,7 +24,7 @@ protected static string GetTableName(Element element) return sql.ToString(); } - private static string GetFieldDataTypeScript(ElementField field) + public static StringBuilder GetFieldDataTypeScript(ElementField field) { var sql = new StringBuilder(); sql.Append(field.DataType.ToString()); @@ -55,10 +55,10 @@ private static string GetFieldDataTypeScript(ElementField field) if (field is { AutoNum: true, DataType: not FieldType.UniqueIdentifier }) sql.Append(" IDENTITY "); - return sql.ToString(); + return sql; } - protected static string GetFieldDefinition(ElementField field) + public static StringBuilder GetFieldDefinition(ElementField field) { var sql = new StringBuilder(); sql.Append('['); @@ -67,10 +67,10 @@ protected static string GetFieldDefinition(ElementField field) sql.Append(GetFieldDataTypeScript(field)); - return sql.ToString(); + return sql; } - protected static string GetSqlDropIfExists(string objname) + public static StringBuilder GetSqlDropIfExists(string objname) { var sql = new StringBuilder(); sql.AppendLine("IF EXISTS (SELECT * "); @@ -90,6 +90,6 @@ protected static string GetSqlDropIfExists(string objname) sql.AppendLine("END"); sql.AppendLine("GO"); - return sql.ToString(); + return sql; } } \ No newline at end of file diff --git a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerWriteProcedureScripts.cs b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerWriteProcedureScripts.cs index a5a492c2e..6636c33b7 100644 --- a/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerWriteProcedureScripts.cs +++ b/src/MasterData.Commons/Data/Entity/Providers/SqlServer/SqlServerWriteProcedureScripts.cs @@ -11,7 +11,6 @@ namespace JJMasterData.Commons.Data.Entity.Providers; public class SqlServerWriteProcedureScripts( IOptionsSnapshot options, IOptionsSnapshot sqlServerOptions) - : SqlServerScriptsBase { private const string InsertInitial = "I"; private const string UpdateInitial = "A"; @@ -34,7 +33,8 @@ public string GetWriteProcedureScript(Element element) } else { - sql.AppendLine(GetSqlDropIfExists(procedureName)); + sql.Append(SqlServerScriptsHelper.GetSqlDropIfExists(procedureName)); + sql.AppendLine(); sql.Append("CREATE PROCEDURE "); } @@ -90,35 +90,35 @@ internal static string GetWriteScript(Element element, IReadOnlyCollection x.IsPk); bool updateScript = HasUpdateFields(element); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @TYPEACTION VARCHAR(1) "); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SET @TYPEACTION = @action "); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("IF @TYPEACTION = ' ' "); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN "); - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.AppendLine($"SET @TYPEACTION = '{InsertInitial}' "); bool isFirst = true; if (pks.Count > 0) { - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.AppendLine("DECLARE @NCOUNT INT "); sql.AppendLine(" "); //Check - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.AppendLine("SELECT @NCOUNT = COUNT(*) "); - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.Append("FROM "); - sql.Append(GetTableName(element)); + sql.Append(SqlServerScriptsHelper.GetTableName(element)); sql.AppendLine(" WITH (NOLOCK) "); foreach (var f in pks) { - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); if (isFirst) { sql.Append("WHERE "); @@ -135,29 +135,29 @@ internal static string GetWriteScript(Element element, IReadOnlyCollection 0 "); - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN "); - sql.Append(Tab).Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.AppendLine($"SET @TYPEACTION = '{UpdateInitial}'"); - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.AppendLine("END "); } - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("END "); sql.AppendLine(" "); //Insert Script - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine($"IF @TYPEACTION = '{InsertInitial}' "); - sql.Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab); sql.AppendLine("BEGIN "); - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); sql.Append("INSERT INTO "); - sql.Append(GetTableName(element)); + sql.Append(SqlServerScriptsHelper.GetTableName(element)); sql.AppendLine(" ("); isFirst = true; @@ -180,7 +180,7 @@ internal static string GetWriteScript(Element element, IReadOnlyCollection 0) { - sql.Append(Tab, 2); + sql.Append(SqlServerScriptsHelper.Tab, 2); sql.Append("OUTPUT "); } @@ -197,7 +197,7 @@ internal static string GetWriteScript(Element element, IReadOnlyCollection f.IsPk)) { - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); if (isFirst) { sql.Append("WHERE "); @@ -272,25 +272,25 @@ internal static string GetWriteScript(Element element, IReadOnlyCollection f.IsPk && f.EnableOnDelete)) { - sql.Append(Tab).Append(Tab); + sql.Append(SqlServerScriptsHelper.Tab).Append(SqlServerScriptsHelper.Tab); if (isFirst) { sql.Append("WHERE "); @@ -306,9 +306,9 @@ internal static string GetWriteScript(Element element, IReadOnlyCollection ExecuteBatchAsync(string script, Guid? connectionId = null) public async Task> GetFieldsAsync(Element element, Dictionary primaryKeys) { if (primaryKeys.Count == 0) - throw new ArgumentException("Your need at least one value at your primary keys.", nameof(primaryKeys)); + throw new ArgumentException(@"Your need at least one value at your primary keys.", nameof(primaryKeys)); var totalOfRecords = new DataAccessParameter("@qtdtotal", 1, DbType.Int32, 0, ParameterDirection.InputOutput); var command = provider.GetReadCommand(element, new EntityParameters diff --git a/src/MasterData.Commons/Extensions/DictionaryExtensions.cs b/src/MasterData.Commons/Extensions/DictionaryExtensions.cs deleted file mode 100644 index e8c93112c..000000000 --- a/src/MasterData.Commons/Extensions/DictionaryExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -#if !NET -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace JJMasterData.Commons.Extensions; - -internal static class DictionaryExtensions -{ - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TValue GetValueOrDefault(this IDictionary dictionary, TKey key, TValue defaultValue) - { - return dictionary.TryGetValue(key, out var value) ? value : defaultValue; - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Commons/MasterData.Commons.csproj b/src/MasterData.Commons/MasterData.Commons.csproj index b0e93038e..da657e4fc 100644 --- a/src/MasterData.Commons/MasterData.Commons.csproj +++ b/src/MasterData.Commons/MasterData.Commons.csproj @@ -1,6 +1,6 @@ - net4.8;net10.0 + net10.0 latest disable JJMasterData.Commons - Sun Version @@ -13,6 +13,7 @@ + @@ -21,23 +22,13 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + @@ -45,4 +36,7 @@ DataAccess.cs + + + diff --git a/src/MasterData.Commons/Resources/MasterDataResources.pt.resx b/src/MasterData.Commons/Resources/MasterDataResources.pt.resx index 5bc80a9f0..880057091 100644 --- a/src/MasterData.Commons/Resources/MasterDataResources.pt.resx +++ b/src/MasterData.Commons/Resources/MasterDataResources.pt.resx @@ -190,6 +190,10 @@ Este campo oferece suporte a valores do runtime entre {}. Use {AppPath} para o caminho da raiz da aplicação. JJMasterDataWeb + + + Este campo oferece suporte a valores do runtime entre {}. + JJMasterDataWeb É Modal? @@ -436,6 +440,10 @@ Limpar Filtro JJMasterDataCore + + + Limpar Filtros + JJMasterDataCore Limpar Log @@ -1736,6 +1744,9 @@ Tipo de lista JJMasterDataWeb + + + Coluna da Chave Coluna da Chave Primária @@ -2605,6 +2616,52 @@ Sincronizar JJMasterData.Commons + + Validações + JJMasterData.Commons + + + Regras + + + Tipo de validação + + + Tipo de regra + + + Ler mais + + + Executa antes do insert + + + Executa antes do update + + + Executa antes do delete + + + Tem certeza que deseja deletar esta regra? + + + Selecione pelo menos uma operação. + + + As regras em JavaScript rodam no servidor com Jint. Use addError(message) para um erro geral ou addError(name, message) para um erro de campo. + + + Antes de inserir e atualizar + + + Retorne uma coluna com a mensagem de erro ou duas colunas com campo e mensagem. Os nomes das colunas não importam. + + + Já existe uma validação com esse nome. + + + Já existe uma regra com esse nome. + Modo do Sincronismo JJMasterDataWeb @@ -3697,9 +3754,6 @@ Quando o painel está no modo visualuização, mostra apenas os valores sem os componentes. - - Valida valores potencialmente perigosos na requisição no .NET Framework 4.8 - Tamanho do campo. Utilize -1 para utilizar a keyword MAX. @@ -3901,9 +3955,6 @@ Ação de Exportação - - Mostrar Upload Fora do Modal - Campo [Nome] não pode começar com número @@ -4224,6 +4275,10 @@ Abrir em uma Nova Aba JJMasterDataWeb + + Assinar Parâmetros com HMAC + JJMasterDataWeb + Deseja recriar a procedure de leitura? Quaisquer modificações feitas na procedure serão perdidas. diff --git a/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionAlgorithm.cs b/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionAlgorithm.cs deleted file mode 100644 index 8df48769a..000000000 --- a/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionAlgorithm.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JJMasterData.Commons.Security.Cryptography.Abstractions; - -/// -/// Represents a secure encryption algorithm. -/// -public interface IEncryptionAlgorithm -{ - public string EncryptString(string plainText, string secretKey); - public string DecryptString(string cipherText, string secretKey); -} \ No newline at end of file diff --git a/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionService.cs b/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionService.cs index 9db595f62..4de897889 100644 --- a/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionService.cs +++ b/src/MasterData.Commons/Security/Cryptography/Abstractions/IEncryptionService.cs @@ -3,6 +3,6 @@ namespace JJMasterData.Commons.Security.Cryptography.Abstractions; public interface IEncryptionService { - string EncryptString(string plainText, string? secretKey = null); - string DecryptString(string cipherText, string? secretKey = null); + string EncryptString(string plainText); + string DecryptString(string cipherText); } \ No newline at end of file diff --git a/src/MasterData.Commons/Security/Cryptography/AesEncryptionAlgorithm.cs b/src/MasterData.Commons/Security/Cryptography/AesEncryptionAlgorithm.cs deleted file mode 100644 index cf5527bbb..000000000 --- a/src/MasterData.Commons/Security/Cryptography/AesEncryptionAlgorithm.cs +++ /dev/null @@ -1,87 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Concurrent; -using System.IO; -using System.Security.Cryptography; -using System.Text; -using JetBrains.Annotations; -using JJMasterData.Commons.Security.Cryptography.Abstractions; - -namespace JJMasterData.Commons.Security.Cryptography; - -/// -/// AES is more secure than the DES cipher and is the de facto world standard. DES can be broken easily as it has known vulnerabilities. -/// -public sealed class AesEncryptionAlgorithm : IEncryptionAlgorithm -{ - private readonly ConcurrentDictionary _aesCache = new(); - - public string EncryptString(string plainText, string secretKey) - { - using var aes = CreateAes(secretKey); - - using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV); - - using var memoryStream = new MemoryStream(); - using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write); - using (var streamWriter = new StreamWriter(cryptoStream)) - { - streamWriter.Write(plainText); - } - - return Convert.ToBase64String(memoryStream.ToArray()); - } - - public string DecryptString(string cipherText, string secretKey) - { - try - { - using var aes = CreateAes(secretKey); - var buffer = Convert.FromBase64String(cipherText); - using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV); - - using var memoryStream = new MemoryStream(buffer); - using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); - using var streamReader = new StreamReader(cryptoStream); - - return streamReader.ReadToEnd(); - } - catch - { - return string.Empty; - } - } - - [MustDisposeResource] - private Aes CreateAes(string secretKey) - { - if (_aesCache.TryGetValue(secretKey, out var aesEntry)) - { - return CreateAes(aesEntry.Key, aesEntry.IV); - } - - var keyBytes = Encoding.UTF8.GetBytes(secretKey); - - using var sha256 = SHA256.Create(); - var aesKey = sha256.ComputeHash(keyBytes); - - using var md5 = MD5.Create(); - var aesIv = md5.ComputeHash(keyBytes); - - aesEntry = new(aesKey, aesIv); - - _aesCache.TryAdd(secretKey, aesEntry); - - return CreateAes(aesEntry.Key, aesEntry.IV); - } - - [MustDisposeResource] - private static Aes CreateAes(byte[] key, byte[] iv) - { - var aes = Aes.Create(); - aes.Key = key; - aes.IV = iv; - return aes; - } -} \ No newline at end of file diff --git a/src/MasterData.Commons/Security/Cryptography/DesEncryptionAlgorithm.cs b/src/MasterData.Commons/Security/Cryptography/DesEncryptionAlgorithm.cs deleted file mode 100644 index 4eaadbdd2..000000000 --- a/src/MasterData.Commons/Security/Cryptography/DesEncryptionAlgorithm.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.IO; -using System.Security.Cryptography; -using System.Text; -using JJMasterData.Commons.Security.Cryptography.Abstractions; - -namespace JJMasterData.Commons.Security.Cryptography; - -/// -/// DES algorithm can be broken easily as it has known vulnerabilities. Please use AesEncryptionService. -/// -public class DesEncryptionAlgorithm : IEncryptionAlgorithm -{ - private static readonly byte[] Iv = [12, 34, 56, 78, 90, 102, 114, 126]; - - public string EncryptString(string plainText, string secretKey) - { - using var des = DES.Create(); - byte[] input = Encoding.UTF8.GetBytes(plainText); - byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey[..8]); - using var ms = new MemoryStream(); - using (var cs = new CryptoStream(ms, des.CreateEncryptor(keyBytes, Iv), CryptoStreamMode.Write)) - { - cs.Write(input, 0, input.Length); - cs.FlushFinalBlock(); - } - return Convert.ToBase64String(ms.ToArray()); - } - - public string DecryptString(string cipherText, string secretKey) - { - if (cipherText == null) - return null; - try - { - using var des = DES.Create(); - using var ms = new MemoryStream(); - var input = Convert.FromBase64String(cipherText.Replace(" ", "+")); - var keyBytes = Encoding.UTF8.GetBytes(secretKey.Substring(0, 8)); - using (var cs = new CryptoStream(ms, des.CreateDecryptor(keyBytes, Iv), CryptoStreamMode.Write)) - { - cs.Write(input, 0, input.Length); - cs.FlushFinalBlock(); - } - - return Encoding.UTF8.GetString(ms.ToArray()); - } - catch - { - return null; - } - - } -} \ No newline at end of file diff --git a/src/MasterData.Commons/Security/Cryptography/EncryptionService.cs b/src/MasterData.Commons/Security/Cryptography/EncryptionService.cs index a1c4ee3c9..b34b8857d 100644 --- a/src/MasterData.Commons/Security/Cryptography/EncryptionService.cs +++ b/src/MasterData.Commons/Security/Cryptography/EncryptionService.cs @@ -1,27 +1,35 @@ #nullable enable -using JJMasterData.Commons.Configuration.Options; + +using System; using JJMasterData.Commons.Security.Cryptography.Abstractions; -using Microsoft.Extensions.Options; +using Microsoft.AspNetCore.DataProtection; namespace JJMasterData.Commons.Security.Cryptography; -/// -/// Wrapper to IEncryptionService with the secret key loaded by IOptions. -/// -public class EncryptionService( - IEncryptionAlgorithm encryptionAlgorithm, - IOptionsSnapshot options) - : IEncryptionService +internal sealed class EncryptionService : IEncryptionService { - private readonly string _secretKey = options.Value.SecretKey!; + private const string Purpose = "JJMasterData.Commons.Security.Cryptography.EncryptionService"; + + private readonly IDataProtector _protector; + + public EncryptionService(IDataProtectionProvider dataProtectionProvider) + { + ArgumentNullException.ThrowIfNull(dataProtectionProvider); - public string EncryptString(string plainText, string? secretKey = null) + _protector = dataProtectionProvider.CreateProtector(Purpose); + } + + public string EncryptString(string plainText) { - return encryptionAlgorithm.EncryptString(plainText,secretKey ??_secretKey); + ArgumentNullException.ThrowIfNull(plainText); + + return _protector.Protect(plainText); } - public string DecryptString(string cipherText, string? secretKey = null) + public string DecryptString(string cipherText) { - return encryptionAlgorithm.DecryptString(cipherText,secretKey ?? _secretKey); + ArgumentNullException.ThrowIfNull(cipherText); + + return _protector.Unprotect(cipherText); } } \ No newline at end of file diff --git a/src/MasterData.Commons/Security/Hashing/Md5HashHelper.cs b/src/MasterData.Commons/Security/Hashing/Md5HashHelper.cs index 71017efee..d0e687585 100644 --- a/src/MasterData.Commons/Security/Hashing/Md5HashHelper.cs +++ b/src/MasterData.Commons/Security/Hashing/Md5HashHelper.cs @@ -8,12 +8,8 @@ public static class Md5HashHelper { public static string ComputeHash(string input) { - byte[] data; - using (var md5Hasher = MD5.Create()) - { - data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input)); - } - + var data = MD5.HashData(Encoding.Default.GetBytes(input)); + var stringBuilder = new StringBuilder(); for (var i = 0; i <= data.Length - 1; i++) { @@ -22,7 +18,7 @@ public static string ComputeHash(string input) return stringBuilder.ToString(); } - + public static bool VerifyHash(string input, string hash) { var hashOfInput = ComputeHash(input); diff --git a/src/MasterData.Commons/Security/HmacHelper.cs b/src/MasterData.Commons/Security/HmacHelper.cs new file mode 100644 index 000000000..3b4f1d6e7 --- /dev/null +++ b/src/MasterData.Commons/Security/HmacHelper.cs @@ -0,0 +1,120 @@ +#nullable enable +using System; +using System.Globalization; +using System.Security.Cryptography; +using System.Text; +using Microsoft.Extensions.Options; + +namespace JJMasterData.Commons.Security; + +public class HmacHelper +{ + private readonly byte[] _key; + private readonly TimeSpan _clockSkew; + + public HmacHelper(IOptions options) + { + var opt = options.Value; + + _key = Encoding.UTF8.GetBytes(opt.SecretKey ?? string.Empty); + _clockSkew = opt.ClockSkew; + } + + public string Generate(string content, DateTime? expiresUtc = null) + { + var contentBytes = Encoding.UTF8.GetBytes(content); + + var ticks = expiresUtc?.ToUniversalTime().Ticks; + + var data = ticks.HasValue + ? Combine(contentBytes, BitConverter.GetBytes(ticks.Value)) + : contentBytes; + + using var hmac = new HMACSHA256(_key); + var fullSig = hmac.ComputeHash(data); + + var truncated = fullSig[..16]; + + var signature = Base64Url(truncated); + + return ticks.HasValue + ? $"{signature}.{ticks.Value}" + : signature; + } + + public bool Validate(string content, string token) + { + if (string.IsNullOrWhiteSpace(token)) + return false; + + var parts = token.Split('.'); + + var signaturePart = parts[0]; + long? ticks = parts.Length > 1 ? long.Parse(parts[1]) : null; + + if (ticks.HasValue) + { + var now = DateTime.UtcNow.Ticks; + if (now > ticks.Value + _clockSkew.Ticks) + return false; + } + + var contentBytes = Encoding.UTF8.GetBytes(content); + + var data = ticks.HasValue + ? Combine(contentBytes, BitConverter.GetBytes(ticks.Value)) + : contentBytes; + + using var hmac = new HMACSHA256(_key); + var expectedFull = hmac.ComputeHash(data); + var expected = expectedFull[..16]; + + var provided = Base64UrlDecode(signaturePart); + + return CryptographicOperations.FixedTimeEquals(expected, provided); + } + + private static byte[] Combine(byte[] a, byte[] b) + { + var result = new byte[a.Length + b.Length]; + Buffer.BlockCopy(a, 0, result, 0, a.Length); + Buffer.BlockCopy(b, 0, result, a.Length, b.Length); + return result; + } + + private static string Base64Url(byte[] input) => + Convert.ToBase64String(input) + .Replace('+', '-') + .Replace('/', '_') + .TrimEnd('='); + + private static byte[] Base64UrlDecode(string input) + { + var padded = input + .Replace('-', '+') + .Replace('_', '/'); + + padded = padded.PadRight(padded.Length + (4 - padded.Length % 4) % 4, '='); + + return Convert.FromBase64String(padded); + } + + public static DateTime? ParseExpirationUtc(string? expirationValue) + { + if (string.IsNullOrWhiteSpace(expirationValue)) return null; + if (long.TryParse(expirationValue, out var ticks)) return new DateTime(ticks, DateTimeKind.Utc); + if (DateTimeOffset.TryParse(expirationValue, CultureInfo.InvariantCulture, + DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var expirationOffset)) + { + return expirationOffset.UtcDateTime; + } + + if (DateTime.TryParse(expirationValue, CultureInfo.InvariantCulture, + DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var expirationDateTime)) + { + return expirationDateTime.ToUniversalTime(); + } + + throw new ArgumentException("Invalid HMAC expiration. Use UTC date/time or ticks."); + } +} \ No newline at end of file diff --git a/src/MasterData.Commons/Security/HmacOptions.cs b/src/MasterData.Commons/Security/HmacOptions.cs new file mode 100644 index 000000000..301a67bc3 --- /dev/null +++ b/src/MasterData.Commons/Security/HmacOptions.cs @@ -0,0 +1,9 @@ +using System; + +namespace JJMasterData.Commons.Security; + +public class HmacOptions +{ + public string SecretKey { get; set; } = string.Empty; + public TimeSpan ClockSkew { get; set; } = TimeSpan.FromMinutes(5); +} \ No newline at end of file diff --git a/src/MasterData.Commons/Storage/DiskFileStorage.cs b/src/MasterData.Commons/Storage/DiskFileStorage.cs new file mode 100644 index 000000000..391f209cb --- /dev/null +++ b/src/MasterData.Commons/Storage/DiskFileStorage.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using JJConsulting.MasterData.Storage.Abstractions; + +namespace JJMasterData.Commons.Storage; + +internal sealed class DiskFileStorage : IFileStorage +{ + public async Task SaveAsync(string fullPath, Stream content, bool replaceIfExists = true, CancellationToken cancellationToken = default) + { + var filePath = FileStoragePath.ResolveFullPath(fullPath); + + var folderPath = Path.GetDirectoryName(filePath); + if (!string.IsNullOrEmpty(folderPath)) + Directory.CreateDirectory(folderPath); + + var mode = replaceIfExists ? FileMode.Create : FileMode.CreateNew; + + if (content.CanSeek) + content.Seek(0, SeekOrigin.Begin); + + await using var fileStream = new FileStream(filePath, mode, FileAccess.Write, FileShare.None, 81920, true); + await content.CopyToAsync(fileStream, cancellationToken); + } + + public Task OpenReadAsync(string fullPath, CancellationToken cancellationToken = default) + { + var filePath = FileStoragePath.ResolveFullPath(fullPath); + Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 81920, true); + return Task.FromResult(stream); + } + + public Task DeleteAsync(string fullPath, CancellationToken cancellationToken = default) + { + var filePath = FileStoragePath.ResolveFullPath(fullPath); + if (File.Exists(filePath)) + File.Delete(filePath); + else + throw new KeyNotFoundException("File not found"); + + return Task.CompletedTask; + } + + public Task DeleteFolderAsync(string folderPath, CancellationToken cancellationToken = default) + { + var resolvedFolderPath = FileStoragePath.ResolveFolderPath(folderPath); + if (Directory.Exists(resolvedFolderPath)) + Directory.Delete(resolvedFolderPath, true); + + return Task.CompletedTask; + } + + public Task MoveAsync(string currentFullPath, string newFullPath, CancellationToken cancellationToken = default) + { + var currentPath = FileStoragePath.ResolveFullPath(currentFullPath); + var newPath = FileStoragePath.ResolveFullPath(newFullPath); + + if (!File.Exists(currentPath)) + throw new KeyNotFoundException("File not found"); + + var newFolderPath = Path.GetDirectoryName(newPath); + if (!string.IsNullOrEmpty(newFolderPath)) + Directory.CreateDirectory(newFolderPath); + + File.Move(currentPath, newPath, true); + + return Task.CompletedTask; + } + + public Task> ListAsync(string folderPath, bool isRecursive = false, CancellationToken cancellationToken = default) + { + var resolvedFolderPath = FileStoragePath.ResolveFolderPath(folderPath); + if (!Directory.Exists(resolvedFolderPath)) + return Task.FromResult(new List()); + + var searchOption = isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + var files = new DirectoryInfo(resolvedFolderPath) + .EnumerateFiles("*", searchOption) + .Select(file => new FileStorageItem + { + FileName = file.Name, + Length = file.Length, + LastWriteTime = file.LastWriteTime, + FolderPath = folderPath + }) + .ToList(); + + return Task.FromResult(files); + } +} diff --git a/src/MasterData.Commons/Storage/FileStorageItemExtensions.cs b/src/MasterData.Commons/Storage/FileStorageItemExtensions.cs new file mode 100644 index 000000000..f27d179fc --- /dev/null +++ b/src/MasterData.Commons/Storage/FileStorageItemExtensions.cs @@ -0,0 +1,20 @@ +using JJConsulting.MasterData.Storage.Abstractions; + +namespace JJMasterData.Commons.Storage; + +public static class FileStorageItemExtensions +{ + extension(FileStorageItem item) + { + public string FullPath + { + get + { + if (string.IsNullOrEmpty(item.FolderPath)) + return FileStoragePath.GetFileName(item.FileName); + + return FileStoragePath.Combine(item.FolderPath, item.FileName); + } + } + } +} \ No newline at end of file diff --git a/src/MasterData.Commons/Storage/FileStoragePath.cs b/src/MasterData.Commons/Storage/FileStoragePath.cs new file mode 100644 index 000000000..60602217a --- /dev/null +++ b/src/MasterData.Commons/Storage/FileStoragePath.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using JJMasterData.Commons.Util; + +namespace JJMasterData.Commons.Storage; + +public static class FileStoragePath +{ + public static string Combine(string folderPath, string fileName) + { + var safeFileName = GetFileName(fileName); + + return string.IsNullOrEmpty(folderPath) + ? safeFileName + : $"{folderPath.TrimEnd('/', '\\')}/{safeFileName}"; + } + + public static string GetFileName(string path) + { + return Path.GetFileName(path?.Replace('\\', '/') ?? string.Empty); + } + + private static string GetFilePath(string folderPath, string fileName) + { + return Path.Combine(folderPath, GetFileName(fileName)); + } + + public static string ResolveFolderPath(string folderPath) + { + if (string.IsNullOrEmpty(folderPath)) + throw new ArgumentNullException(nameof(folderPath)); + + var separator = Path.DirectorySeparatorChar; + var resolvedFolderPath = folderPath.Replace("{app.path}", FileIO.GetApplicationPath().TrimEnd(separator)); + + return Path.GetFullPath(resolvedFolderPath); + } + + public static string ResolveFullPath(string fullPath) + { + if (string.IsNullOrEmpty(fullPath)) + throw new ArgumentNullException(nameof(fullPath)); + + var normalizedFullPath = fullPath.Replace('\\', '/'); + var folderPath = Path.GetDirectoryName(normalizedFullPath); + if (string.IsNullOrEmpty(folderPath)) + throw new ArgumentException(@"File path must include a folder.", nameof(fullPath)); + + var resolvedFolderPath = ResolveFolderPath(folderPath); + + return GetFilePath(resolvedFolderPath, GetFileName(normalizedFullPath)); + } +} diff --git a/src/MasterData.Commons/Storage/StorageCollectionExtensions.cs b/src/MasterData.Commons/Storage/StorageCollectionExtensions.cs new file mode 100644 index 000000000..f0c8a80ff --- /dev/null +++ b/src/MasterData.Commons/Storage/StorageCollectionExtensions.cs @@ -0,0 +1,25 @@ +using System; +using JJConsulting.MasterData.Storage.Abstractions; +using JJMasterData.Commons.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace JJMasterData.Commons.Storage; + +public static class MasterDataServiceCollectionExtensions +{ + extension(MasterDataServiceBuilder builder) + { + public MasterDataServiceBuilder WithFileStorage(Func implementationFactory) + { + builder.Services.Replace(ServiceDescriptor.Transient(implementationFactory)); + return builder; + } + + public MasterDataServiceBuilder WithFileStorage() where T : IFileStorage + { + builder.Services.Replace(ServiceDescriptor.Transient(typeof(IFileStorage),typeof(T))); + return builder; + } + } +} \ No newline at end of file diff --git a/src/MasterData.Commons/Util/CountryHelper.cs b/src/MasterData.Commons/Util/CountryHelper.cs index 0b504b0fb..02d9ff78f 100644 --- a/src/MasterData.Commons/Util/CountryHelper.cs +++ b/src/MasterData.Commons/Util/CountryHelper.cs @@ -4,7 +4,7 @@ using System.Collections.ObjectModel; using System.Linq; -namespace JJMasterData.Core.DataDictionary.Services; +namespace JJMasterData.Commons.Util; public enum CountryCode { diff --git a/src/MasterData.Commons/Util/DictionaryHash.cs b/src/MasterData.Commons/Util/DictionaryHash.cs index e376786fc..e73a2d7c5 100644 --- a/src/MasterData.Commons/Util/DictionaryHash.cs +++ b/src/MasterData.Commons/Util/DictionaryHash.cs @@ -13,14 +13,8 @@ public static string ComputeHash(Dictionary dict) { var ordered = dict.OrderBy(x => x.Key); var json = JsonSerializer.Serialize(ordered); - - using var sha = SHA256.Create(); - var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(json)); - - #if NETFRAMEWORK - return BitConverter.ToString(bytes).Replace("-", ""); - #else + var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(json)); + return Convert.ToHexString(bytes); - #endif } -} \ No newline at end of file +} diff --git a/src/MasterData.Commons/Util/FileIO.cs b/src/MasterData.Commons/Util/FileIO.cs index b2f6d44f9..ee799e177 100644 --- a/src/MasterData.Commons/Util/FileIO.cs +++ b/src/MasterData.Commons/Util/FileIO.cs @@ -2,8 +2,6 @@ using System.Data; using System.Globalization; using System.IO; -using JJMasterData.Commons.Configuration.Options; - namespace JJMasterData.Commons.Util; public static class FileIO @@ -50,13 +48,11 @@ public static string ResolveFilePath(string filepath) /// /// Returns the application path. - /// .NET Framework: AppDomain.CurrentDomain.BaseDirectory - /// ..NET 8+: Environment.CurrentDirectory /// /// public static string GetApplicationPath() { - return MasterDataCommonsOptions.IsNetFramework ? AppDomain.CurrentDomain.BaseDirectory : Environment.CurrentDirectory; + return Environment.CurrentDirectory; } /// diff --git a/src/MasterData.Commons/Util/MimeTypeUtil.cs b/src/MasterData.Commons/Util/MimeTypeUtil.cs index 929f617c4..e5a807bad 100644 --- a/src/MasterData.Commons/Util/MimeTypeUtil.cs +++ b/src/MasterData.Commons/Util/MimeTypeUtil.cs @@ -2,10 +2,6 @@ using System.Collections.Frozen; using System.Collections.Generic; -#if NET48 -using JJMasterData.Commons.Extensions; -#endif - namespace JJMasterData.Commons.Util; public static class MimeTypeUtil @@ -248,6 +244,7 @@ public static class MimeTypeUtil {".manifest", "application/x-ms-manifest"}, {".map", "text/plain"}, {".master", "application/xml"}, + {".md", "text/markdown"}, {".mda", "application/msaccess"}, {".mdb", "application/x-msaccess"}, {".mde", "application/msaccess"}, @@ -596,4 +593,4 @@ public static string GetMimeType(string extension) return Mappings.GetValueOrDefault(extension, "application/octet-stream"); } -} \ No newline at end of file +} diff --git a/src/MasterData.Commons/Util/StringManager.cs b/src/MasterData.Commons/Util/StringManager.cs index ff7fa91b7..9223e690b 100644 --- a/src/MasterData.Commons/Util/StringManager.cs +++ b/src/MasterData.Commons/Util/StringManager.cs @@ -462,21 +462,12 @@ private static string Soma1(string baseVal, int size) public static string FirstCharToUpper(this string input) { - //Since .NET Core 3.0 / .NET Standard 2.1 String.Concat() - //supports ReadonlySpan which saves one allocation if we use .AsSpan(1) instead of .Substring(1). -#if NET return input switch { null => throw new ArgumentNullException(nameof(input)), "" => throw new ArgumentException(@$"{nameof(input)} cannot be empty", nameof(input)), _ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1)) }; -#else - if (!string.IsNullOrEmpty(input)) - return input[0].ToString().ToUpper() + input[1..].ToLower(); - return input; -#endif - } public static string ToParamCase(string input) diff --git a/src/MasterData.Commons/Validations/Validations.cs b/src/MasterData.Commons/Validations/Validations.cs index ad30cdfd2..5699af66e 100644 --- a/src/MasterData.Commons/Validations/Validations.cs +++ b/src/MasterData.Commons/Validations/Validations.cs @@ -23,7 +23,7 @@ public static bool ValidateCnpj(string cnpj) /// E-Mail public static bool ValidateEmail(string email) { - if (email.Contains("'")) + if (email.Contains('\'')) return false; if (email.Contains('@') && email.Contains('.') && !email.Contains("..")) diff --git a/src/MasterData.Core/Configuration/ActionsServiceExtensions.cs b/src/MasterData.Core/Configuration/ActionsServiceExtensions.cs index 8153bcacb..b7a8570db 100644 --- a/src/MasterData.Core/Configuration/ActionsServiceExtensions.cs +++ b/src/MasterData.Core/Configuration/ActionsServiceExtensions.cs @@ -15,7 +15,7 @@ public static IServiceCollection AddActionServices(this IServiceCollection servi AllowParentheses = true })); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); return services; } diff --git a/src/MasterData.Core/Configuration/DataDictionaryServiceExtensions.cs b/src/MasterData.Core/Configuration/DataDictionaryServiceExtensions.cs index 766880d2f..04c4c0736 100644 --- a/src/MasterData.Core/Configuration/DataDictionaryServiceExtensions.cs +++ b/src/MasterData.Core/Configuration/DataDictionaryServiceExtensions.cs @@ -20,6 +20,7 @@ public static IServiceCollection AddDataDictionaryServices(this IServiceCollecti services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); return services; diff --git a/src/MasterData.Core/Configuration/DataManagerServiceExtensions.cs b/src/MasterData.Core/Configuration/DataManagerServiceExtensions.cs index 3afeefef7..d1a0fbcb4 100644 --- a/src/MasterData.Core/Configuration/DataManagerServiceExtensions.cs +++ b/src/MasterData.Core/Configuration/DataManagerServiceExtensions.cs @@ -1,7 +1,10 @@ +using JJMasterData.Commons.Storage; using JJMasterData.Core.DataManager; -using JJMasterData.Core.DataManager.IO; using JJMasterData.Core.DataManager.Services; +using JJMasterData.Core.DataManager.Services.Abstractions; +using JJMasterData.Core.UI.Components; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace JJMasterData.Core.Configuration; @@ -9,24 +12,28 @@ public static class DataManagerServiceExtensions { public static IServiceCollection AddDataManagerServices(this IServiceCollection services) { - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); -#if NET - services.AddScoped(); -#endif - services.AddScoped(); - services.AddScoped(); + services.TryAddScoped(); + + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + + services.TryAddEnumerable(ServiceDescriptor.Scoped()); + services.TryAddEnumerable(ServiceDescriptor.Scoped()); + + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); return services; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/Configuration/FactoriesServiceExtensions.cs b/src/MasterData.Core/Configuration/FactoriesServiceExtensions.cs index bf31fb3c4..93eb634f5 100644 --- a/src/MasterData.Core/Configuration/FactoriesServiceExtensions.cs +++ b/src/MasterData.Core/Configuration/FactoriesServiceExtensions.cs @@ -1,4 +1,3 @@ -using JJConsulting.Html.Bootstrap.Components; using JJMasterData.Core.DataDictionary.Structure; using JJMasterData.Core.DataManager.Exportation; using JJMasterData.Core.DataManager.Importation; diff --git a/src/MasterData.Core/Configuration/HttpServiceExtensions.cs b/src/MasterData.Core/Configuration/HttpServiceExtensions.cs index 036190000..2a1367ff5 100644 --- a/src/MasterData.Core/Configuration/HttpServiceExtensions.cs +++ b/src/MasterData.Core/Configuration/HttpServiceExtensions.cs @@ -1,10 +1,6 @@ -using JJMasterData.Core.Http; -using JJMasterData.Core.Http.Abstractions; -using Microsoft.Extensions.DependencyInjection; -#if NET using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; -#endif +using Microsoft.Extensions.DependencyInjection; namespace JJMasterData.Core.Configuration; @@ -12,16 +8,7 @@ public static class HttpServiceExtensions { public static void AddHttpServices(this IServiceCollection services) { - services.AddScoped(); -#if NET services.AddHttpContextAccessor(); - services.AddScoped(); - - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); #pragma warning disable ASPDEPR006 services.AddSingleton(); @@ -33,19 +20,5 @@ public static void AddHttpServices(this IServiceCollection services) var urlHelperFactory = serviceProvider.GetRequiredService(); return urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext!); }); -#endif - - -#if NETFRAMEWORK - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); -#endif - - } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/Configuration/MasterDataServiceBuilderExtensions.cs b/src/MasterData.Core/Configuration/MasterDataServiceBuilderExtensions.cs index 0158b56c7..393e57910 100644 --- a/src/MasterData.Core/Configuration/MasterDataServiceBuilderExtensions.cs +++ b/src/MasterData.Core/Configuration/MasterDataServiceBuilderExtensions.cs @@ -1,7 +1,4 @@ -#nullable enable - -using System; -using System.Reflection; +using System; using JJMasterData.Commons.Configuration; using JJMasterData.Commons.Data; using JJMasterData.Commons.Data.Entity.Repository.Abstractions; diff --git a/src/MasterData.Core/Configuration/Options/MasterDataCoreOptions.cs b/src/MasterData.Core/Configuration/Options/MasterDataCoreOptions.cs index 44a8b28a3..e2568c6bd 100644 --- a/src/MasterData.Core/Configuration/Options/MasterDataCoreOptions.cs +++ b/src/MasterData.Core/Configuration/Options/MasterDataCoreOptions.cs @@ -1,10 +1,6 @@ -#nullable enable - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.IO; -using System.Linq; using System.Security.Claims; using JJMasterData.Commons.Util; using NCalc; @@ -33,37 +29,37 @@ public sealed class MasterDataCoreOptions [Display(Name = "Audit Log Table Name")] public string AuditLogTableName { get; set; } = "tb_masterdata_auditlog"; -#if !NET - /// - /// Default value: null - /// - public string? MasterDataUrl { get; set; } - - public bool EnableCultureProviderAtUrl { get; set; } = true; -#endif - [Display(Name = "Enable Data Dictionary Caching")] public bool EnableDataDictionaryCaching { get; set; } = true; /// - /// Default value: {ApplicationPath}/JJExportationFiles + /// Default value: {app.path}/JJExportationFiles /// [Display(Name = "Exportation Folder Path")] - public string ExportationFolderPath { get; set; } = Path.Combine(FileIO.GetApplicationPath(), "JJExportationFiles"); + public string ExportationFolderPath { get; set; } = "{app.path}/JJExportationFiles"; public string UserIdClaimType { get; set; } = ClaimTypes.NameIdentifier; + /// + /// Configuration of expression + /// + public ExpressionConfiguration ExpressionConfiguration { get; set; } = new() + { + Evaluation = new ExpressionEvaluationOptions + { + AllowNullParameter = true, + AllowNullOrEmptyExpressions = true, + IgnoreCaseAtBuiltInFunctions = true, + ArithmeticNullOrEmptyStringAsZero = true, + StringComparer = StringComparer.OrdinalIgnoreCase, + } + }; + /// /// Context of expressions starting with "exp:". Declare here custom parameters and functions. /// public ExpressionContext ExpressionContext { get; set; } = new() { - Options = ExpressionOptions.IgnoreCaseAtBuiltInFunctions - | ExpressionOptions.AllowNullParameter - | ExpressionOptions.OrdinalStringComparer - | ExpressionOptions.AllowNullOrEmptyExpressions - | ExpressionOptions.ArithmeticNullOrEmptyStringAsZero - | ExpressionOptions.CaseInsensitiveStringComparer, Functions = new Dictionary(StringComparer.InvariantCultureIgnoreCase) { { @@ -78,7 +74,7 @@ public sealed class MasterDataCoreOptions { "iif", args => { - if (args.Count() != 3) + if (args.Count != 3) throw new NCalcEvaluationException("iif() takes exactly 3 arguments."); var conditional = StringManager.ParseBool(args.Evaluate(0)); return conditional ? args.Evaluate(1) : args.Evaluate(2); @@ -87,7 +83,7 @@ public sealed class MasterDataCoreOptions { "len", args => { - if (args.Count() != 1) + if (args.Count != 1) { throw new NCalcEvaluationException("len() takes exactly 1 argument."); } @@ -105,7 +101,29 @@ public sealed class MasterDataCoreOptions return args.Evaluate(0)?.ToString()?.Trim(); } + }, + { + "coalesce", args => + { + if (args.Count == 0) + throw new NCalcEvaluationException("coalesce() takes at least 1 argument."); + + for (var i = 0; i < args.Count; i++) + { + var value = args.Evaluate(i); + + if (value == null) + continue; + + if (value is string str && string.IsNullOrEmpty(str)) + continue; + + return value; + } + + return null; + } } } }; -} \ No newline at end of file +} diff --git a/src/MasterData.Core/Configuration/Options/MasterDataCoreOptionsConfiguration.cs b/src/MasterData.Core/Configuration/Options/MasterDataCoreOptionsConfiguration.cs index 97cc9dee3..950b68d98 100644 --- a/src/MasterData.Core/Configuration/Options/MasterDataCoreOptionsConfiguration.cs +++ b/src/MasterData.Core/Configuration/Options/MasterDataCoreOptionsConfiguration.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using JJMasterData.Commons.Configuration.Options; namespace JJMasterData.Core.Configuration.Options; diff --git a/src/MasterData.Core/Configuration/ServiceCollectionExtensions.cs b/src/MasterData.Core/Configuration/ServiceCollectionExtensions.cs index 9d88a0ec5..43cfddcdd 100644 --- a/src/MasterData.Core/Configuration/ServiceCollectionExtensions.cs +++ b/src/MasterData.Core/Configuration/ServiceCollectionExtensions.cs @@ -4,7 +4,6 @@ using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Exportation; using JJMasterData.Core.DataManager.Exportation.Abstractions; -using JJMasterData.Core.Html; using JJMasterData.Core.Html.Templates; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -13,54 +12,53 @@ namespace JJMasterData.Core.Configuration; public static class ServiceCollectionExtensions { - public static MasterDataServiceBuilder AddJJMasterDataCore(this IServiceCollection services) + extension(IServiceCollection services) { - services.AddMasterDataCoreServices(); + public MasterDataServiceBuilder AddJJMasterDataCore() + { + services.AddMasterDataCoreServices(); - return services.AddJJMasterDataCommons(); - } + return services.AddJJMasterDataCommons(); + } - public static MasterDataServiceBuilder AddJJMasterDataCore( - this IServiceCollection services, - MasterDataCoreOptionsConfiguration optionsConfiguration + public MasterDataServiceBuilder AddJJMasterDataCore(MasterDataCoreOptionsConfiguration optionsConfiguration ) - { - if (optionsConfiguration.ConfigureCore != null) - services.PostConfigure(optionsConfiguration.ConfigureCore); + { + if (optionsConfiguration.ConfigureCore != null) + services.PostConfigure(optionsConfiguration.ConfigureCore); - services.AddMasterDataCoreServices(); - return services.AddJJMasterDataCommons(optionsConfiguration.ConfigureCommons); - } + services.AddMasterDataCoreServices(); + return services.AddJJMasterDataCommons(optionsConfiguration.ConfigureCommons); + } - public static MasterDataServiceBuilder AddJJMasterDataCore(this IServiceCollection services, - IConfiguration configuration) - { - services.Configure(configuration.GetJJMasterData()); + public MasterDataServiceBuilder AddJJMasterDataCore(IConfiguration configuration) + { + services.Configure(configuration.GetJJMasterData()); - services.AddMasterDataCoreServices(); + services.AddMasterDataCoreServices(); - return services.AddJJMasterDataCommons(configuration); - } + return services.AddJJMasterDataCommons(configuration); + } - private static void AddMasterDataCoreServices(this IServiceCollection services) - { - services.AddOptions().BindConfiguration("JJMasterData"); + private void AddMasterDataCoreServices() + { + services.AddOptions().BindConfiguration("JJMasterData"); - services.AddHttpServices(); - services.AddDataDictionaryServices(); - services.AddDataManagerServices(); - services.AddEventHandlers(); - services.AddExpressionServices(); - services.AddActionServices(); + services.AddHttpServices(); + services.AddDataDictionaryServices(); + services.AddDataManagerServices(); + services.AddEventHandlers(); + services.AddExpressionServices(); + services.AddActionServices(); - services.AddScoped(); + services.AddScoped(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddScoped(); - services.AddScoped(); + services.AddScoped(); + services.AddScoped(); - services.AddFactories(); + services.AddFactories(); + } } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/BasicAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/BasicAction.cs index 125123717..1f578d897 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/BasicAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/BasicAction.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/FormElementActionList.cs b/src/MasterData.Core/DataDictionary/Models/Actions/FormElementActionList.cs index 34003ea74..6ff65900d 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/FormElementActionList.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/FormElementActionList.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections; using System.Collections.Generic; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/BackAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/BackAction.cs index 7be495ba0..1743f5e51 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/BackAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/BackAction.cs @@ -1,6 +1,3 @@ -#nullable enable - - using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/CancelAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/CancelAction.cs index 80792638e..0daa9ec03 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/CancelAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/CancelAction.cs @@ -1,6 +1,3 @@ -#nullable enable - - using JJConsulting.FontAwesome; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/SaveAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/SaveAction.cs index 17be36dba..eb95a600e 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/SaveAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/FormToolbar/SaveAction.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/EditAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/EditAction.cs index 62efdf785..5f07b2b15 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/EditAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/EditAction.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +#nullable disable warnings +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/ViewAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/ViewAction.cs index 1ad7dc9c3..96e400c40 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/ViewAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/GridTable/ViewAction.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +#nullable disable warnings +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ExportAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ExportAction.cs index 8380ee6b7..1b5e3f783 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ExportAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ExportAction.cs @@ -1,6 +1,4 @@ - -#nullable enable -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ImportAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ImportAction.cs index 323747108..7925e8eb4 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ImportAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/ImportAction.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/InsertAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/InsertAction.cs index aa463d007..e29b73762 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/InsertAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/GridToolbar/InsertAction.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +#nullable disable warnings +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; @@ -22,7 +23,7 @@ public sealed class InsertAction : GridToolbarAction, IModalAction /// [JsonPropertyName("elementNameToSelect")] [Display(Name = "Element Name To Select")] - public string ElementNameToSelect { get; set; } + public string? ElementNameToSelect { get; set; } /// /// Re-opens the insert after saving. @@ -37,7 +38,7 @@ public sealed class InsertAction : GridToolbarAction, IModalAction [Display(Name = "Modal Title")] [JsonPropertyName("modalTitle")] - public string ModalTitle { get; set; } + public string? ModalTitle { get; set; } [Display(Name = "Success Message")] [JsonPropertyName("successMessage")] diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/HtmlTemplateAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/HtmlTemplateAction.cs index dc04e1dc5..5e46b20fa 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/HtmlTemplateAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/HtmlTemplateAction.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginActionHandler.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginActionHandler.cs index c28f1cdfc..513112b81 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginActionHandler.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginActionHandler.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.Threading.Tasks; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginFieldActionHandler.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginFieldActionHandler.cs index 1c9a40285..20f9aed13 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginFieldActionHandler.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginFieldActionHandler.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginHandler.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginHandler.cs index da5a19c8a..ef4e82a7a 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginHandler.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/IPluginHandler.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginAction.cs index 2fc870b79..9dc4df982 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginAction.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionContext.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionContext.cs index 973dbaa69..d33b31812 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionContext.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionContext.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.Collections.Generic; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionResult.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionResult.cs index 8fcbd5af3..165b45f19 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionResult.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginActionResult.cs @@ -1,5 +1,3 @@ -#nullable enable - using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginConfigurationField.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginConfigurationField.cs index 5f5862d3c..41248ab7c 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginConfigurationField.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginConfigurationField.cs @@ -1,5 +1,3 @@ -#nullable enable - namespace JJMasterData.Core.DataDictionary.Models.Actions; public class PluginConfigurationField diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldAction.cs index d546074c0..7e9c0c19c 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldAction.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Collections.Generic; using System.ComponentModel; using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldActionContext.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldActionContext.cs index ca6491d07..5510c345c 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldActionContext.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Plugins/PluginFieldActionContext.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Collections.Generic; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/ScriptAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/ScriptAction.cs index c0a466cf3..dfda372fd 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/ScriptAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/ScriptAction.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +#nullable disable warnings +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JetBrains.Annotations; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/ActionListConverterBase.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/ActionListConverterBase.cs index 53b6acad3..85aff56c3 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/ActionListConverterBase.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/ActionListConverterBase.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using System.Collections.Generic; using System.Text.Json; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormElementFieldActionListConverter.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormElementFieldActionListConverter.cs index 37110c9d0..51d996883 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormElementFieldActionListConverter.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormElementFieldActionListConverter.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Text.Json; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormToolbarActionListConverter.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormToolbarActionListConverter.cs index ca84a075e..99a34560f 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormToolbarActionListConverter.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/FormToolbarActionListConverter.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Text.Json; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridTableActionListConverter.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridTableActionListConverter.cs index d1f1aec87..27f1faf87 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridTableActionListConverter.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridTableActionListConverter.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Text.Json; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridToolbarActionListConverter.cs b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridToolbarActionListConverter.cs index 0500628dc..b3f0d14f6 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridToolbarActionListConverter.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/Serialization/GridToolbarActionListConverter.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Text.Json; namespace JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/SqlCommandAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/SqlCommandAction.cs index 58dd2b76e..3eaba9036 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/SqlCommandAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/SqlCommandAction.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; diff --git a/src/MasterData.Core/DataDictionary/Models/Actions/UrlRedirectAction.cs b/src/MasterData.Core/DataDictionary/Models/Actions/UrlRedirectAction.cs index 87f36baa5..681fc748d 100644 --- a/src/MasterData.Core/DataDictionary/Models/Actions/UrlRedirectAction.cs +++ b/src/MasterData.Core/DataDictionary/Models/Actions/UrlRedirectAction.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +#nullable disable warnings +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; using JJConsulting.Html.Bootstrap.Models; @@ -32,6 +33,10 @@ public sealed class UrlRedirectAction : BasicAction [JsonPropertyName("encryptParameters")] [Display(Name="Encrypt Parameters")] public bool EncryptParameters { get; set; } + + [JsonPropertyName("signParametersWithHmac")] + [Display(Name = "Sign Parameters with HMAC")] + public bool SignParametersWithHmac { get; set; } [JsonPropertyName("openInNewTab")] [Display(Name="Open in New Tab")] @@ -45,4 +50,4 @@ public UrlRedirectAction() public override bool IsUserDefined => true; public override BasicAction DeepCopy() => (BasicAction)MemberwiseClone(); -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Models/DataElementMap.cs b/src/MasterData.Core/DataDictionary/Models/DataElementMap.cs index 4036b9fa0..9e8aeb5ad 100644 --- a/src/MasterData.Core/DataDictionary/Models/DataElementMap.cs +++ b/src/MasterData.Core/DataDictionary/Models/DataElementMap.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.Html.Bootstrap.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/DataElementMapFilter.cs b/src/MasterData.Core/DataDictionary/Models/DataElementMapFilter.cs index 7e8f665ec..c41f293ec 100644 --- a/src/MasterData.Core/DataDictionary/Models/DataElementMapFilter.cs +++ b/src/MasterData.Core/DataDictionary/Models/DataElementMapFilter.cs @@ -1,6 +1,6 @@ -using System.ComponentModel.DataAnnotations; +#nullable disable warnings +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; -using JJMasterData.Commons.Data.Entity.Models; namespace JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/DataItemValue.cs b/src/MasterData.Core/DataDictionary/Models/DataItemValue.cs index 305287214..fc9d0e948 100644 --- a/src/MasterData.Core/DataDictionary/Models/DataItemValue.cs +++ b/src/MasterData.Core/DataDictionary/Models/DataItemValue.cs @@ -1,8 +1,9 @@ -using System.Text.Json.Serialization; +#nullable disable warnings +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; using JetBrains.Annotations; using JJConsulting.FontAwesome; - namespace JJMasterData.Core.DataDictionary.Models; /// @@ -12,18 +13,17 @@ namespace JJMasterData.Core.DataDictionary.Models; public class DataItemValue { [JsonPropertyName("id")] - public string Id { get; set; } + public required string Id { get; set; } [JsonPropertyName("description")] - [CanBeNull] - public string Description { get; set; } + public string? Description { get; set; } [CanBeNull] [JsonPropertyName("imageUrl")] - public string ImageUrl { get; set; } + public string? ImageUrl { get; set; } [JsonPropertyName("icon")] - public FontAwesomeIcon Icon { get; set; } + public FontAwesomeIcon? Icon { get; set; } /// /// Image color in hexadecimal. @@ -32,19 +32,21 @@ public class DataItemValue /// #FF112F1 /// [JsonPropertyName("imagecolor")] - public string IconColor { get; set; } + public string? IconColor { get; set; } - [JsonPropertyName("group")] - [CanBeNull] - public string Group { get; set; } + [JsonPropertyName("group")] + public string? Group { get; set; } public DataItemValue() { } + [SetsRequiredMembers] public DataItemValue(string id, string description) { Id = id; Description = description; } + + [SetsRequiredMembers] public DataItemValue(string id, string description, FontAwesomeIcon icon, string iconColor) { Id = id; @@ -57,4 +59,4 @@ public DataItemValue DeepCopy() { return (DataItemValue)MemberwiseClone(); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Models/ElementBean.cs b/src/MasterData.Core/DataDictionary/Models/ElementBean.cs index ef2b91fb4..e6e7c6b19 100644 --- a/src/MasterData.Core/DataDictionary/Models/ElementBean.cs +++ b/src/MasterData.Core/DataDictionary/Models/ElementBean.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.ComponentModel.DataAnnotations; namespace JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/Entity.cs b/src/MasterData.Core/DataDictionary/Models/Entity.cs index 2659e2af7..b76d7b4f4 100644 --- a/src/MasterData.Core/DataDictionary/Models/Entity.cs +++ b/src/MasterData.Core/DataDictionary/Models/Entity.cs @@ -1,10 +1,7 @@ -#nullable enable -using System; +using System; using System.ComponentModel.DataAnnotations; using JJConsulting.FontAwesome; using JJConsulting.Html.Bootstrap.Models; -using JJMasterData.Commons.Data.Entity.Models; -using JJMasterData.Core.UI.Components; namespace JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/FormActionRedirect.cs b/src/MasterData.Core/DataDictionary/Models/FormActionRedirect.cs index 700515fec..0b187b82f 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormActionRedirect.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormActionRedirect.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.Html.Bootstrap.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/FormActionRelationField.cs b/src/MasterData.Core/DataDictionary/Models/FormActionRelationField.cs index 2bacbacc6..30f3e69c3 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormActionRelationField.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormActionRelationField.cs @@ -1,4 +1,5 @@ - +#nullable disable warnings + using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElement.cs b/src/MasterData.Core/DataDictionary/Models/FormElement.cs index 7543b6a85..8f33a57d9 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElement.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElement.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data; @@ -69,6 +67,10 @@ public class FormElement : Element [JsonPropertyName("options")] public FormElementOptions Options { get; set; } + [Required] + [JsonPropertyName("rules")] + public List Rules { get; set; } + [Required] [JsonPropertyName("apiOptions")] public FormElementApiOptions ApiOptions { get; set; } @@ -78,6 +80,7 @@ public FormElement() Fields = new FormElementFieldList(base.Fields); Panels = []; Options = new FormElementOptions(); + Rules = []; Relationships = new FormElementRelationshipList(base.Relationships); ApiOptions = new FormElementApiOptions(); } @@ -102,6 +105,7 @@ public FormElement(Element element) Panels = []; ApiOptions = new FormElementApiOptions(); Options = new FormElementOptions(); + Rules = []; } [SetsRequiredMembers] @@ -139,6 +143,7 @@ private FormElement( List? panels, FormElementRelationshipList relationships, FormElementOptions? options, + List? rules, FormElementApiOptions? apiOptions) { base.Fields = new ElementFieldList(fields.Cast().ToList()); @@ -149,6 +154,7 @@ private FormElement( .ToList()!; Relationships = relationships; Options = options ?? new FormElementOptions(); + Rules = rules ?? []; ApiOptions = apiOptions ?? new FormElementApiOptions(); Panels = panels ?? []; } @@ -226,6 +232,7 @@ public FormElement DeepCopy() copy.Fields = Fields.DeepCopy(); copy.Options = Options.DeepCopy(); + copy.Rules = Rules.ConvertAll(v => v.DeepCopy()); copy.Panels = Panels.ConvertAll(p => p.DeepCopy()); copy.Relationships = Relationships.DeepCopy(); copy.Indexes = Indexes.ConvertAll(i => i.DeepCopy()); @@ -233,4 +240,9 @@ public FormElement DeepCopy() return copy; } + + public FormElementRule GetRuleById(int id) + { + return Rules.First(v => v.Id == id); + } } diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementApiOptions.cs b/src/MasterData.Core/DataDictionary/Models/FormElementApiOptions.cs index 72fd22a23..18649fbe2 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementApiOptions.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementApiOptions.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementDataFile.cs b/src/MasterData.Core/DataDictionary/Models/FormElementDataFile.cs index 04f983fef..bd198e486 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementDataFile.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementDataFile.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; @@ -63,12 +61,8 @@ public class FormElementDataFile [Display(Name = "Allow pasting files")] public bool AllowPasting { get; set; } = true; - [JsonPropertyName("showAsUploadView")] - [Display(Name = "Show Upload Outside Modal")] - public bool ShowAsUploadView { get; set; } - public FormElementDataFile DeepCopy() { return (FormElementDataFile)MemberwiseClone(); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementDataItem.cs b/src/MasterData.Core/DataDictionary/Models/FormElementDataItem.cs index a9626a7a0..12eace427 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementDataItem.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementDataItem.cs @@ -1,6 +1,6 @@ -#nullable enable -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using JJMasterData.Commons.Data; @@ -76,10 +76,13 @@ public class FormElementDataItem public bool SupportsFloatingLabels() => !EnableMultiSelect && !ShowIcon; + [MemberNotNullWhen(true, nameof(Command))] public bool HasSqlCommand() => !string.IsNullOrWhiteSpace(Command?.Sql); + [MemberNotNullWhen(true, nameof(ElementMap))] public bool HasElementMap() => ElementMap != null; + [MemberNotNullWhen(true, nameof(Items))] public bool HasItems() => Items?.Count > 0; public FormElementDataItem DeepCopy() diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementField.cs b/src/MasterData.Core/DataDictionary/Models/FormElementField.cs index 94d11efdf..1c2bb109f 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementField.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementField.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; @@ -122,17 +120,6 @@ public class FormElementField : ElementField [Display(Name = "Enable Exportation")] public bool Export { get; set; } - /// - /// Validates possibly dangerous values in the request for .NET Framework - /// - /// - /// Important for lower versions of .NET Framework to enable the parameter: - /// httpRuntime requestValidationMode="4.5" ... - /// - [JsonPropertyName("validateRequest")] - [Display(Name = "Validate Request")] - public bool ValidateRequest { get; set; } - /// /// Ao alterar o conteúdo recarrega todos os campos do formulário /// (Default=false) @@ -201,7 +188,6 @@ public FormElementField() { Component = FormComponent.Text; Export = true; - ValidateRequest = true; VisibleExpression = "val:1"; EnableExpression = "val:1"; TextCase = TextCase.None; @@ -254,9 +240,8 @@ public FormElementField(ElementField elementField) } Export = true; - ValidateRequest = true; TextCase = TextCase.None; - Actions = new(); + Actions = []; } diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementFieldList.cs b/src/MasterData.Core/DataDictionary/Models/FormElementFieldList.cs index 5cad7644a..826395b4c 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementFieldList.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementFieldList.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementFieldSelector.cs b/src/MasterData.Core/DataDictionary/Models/FormElementFieldSelector.cs index fd19626c1..b18a24215 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementFieldSelector.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementFieldSelector.cs @@ -1,6 +1,4 @@ -#nullable enable - -namespace JJMasterData.Core.DataDictionary.Models; +namespace JJMasterData.Core.DataDictionary.Models; public class FormElementFieldSelector(FormElement formElement, string fieldName) { diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementInfo.cs b/src/MasterData.Core/DataDictionary/Models/FormElementInfo.cs index d809b28d8..f137737e5 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementInfo.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementInfo.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementOptions.cs b/src/MasterData.Core/DataDictionary/Models/FormElementOptions.cs index 9c87ae2f2..9dcf2a9b1 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementOptions.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementOptions.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementPanel.cs b/src/MasterData.Core/DataDictionary/Models/FormElementPanel.cs index b0869c6d3..7d845b77d 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementPanel.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementPanel.cs @@ -1,10 +1,7 @@ -#nullable enable - -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.FontAwesome; using JJConsulting.Html.Bootstrap.Models; -using JJMasterData.Commons.Data.Entity.Models; namespace JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementRelationship.cs b/src/MasterData.Core/DataDictionary/Models/FormElementRelationship.cs index 865478bde..14fd376aa 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementRelationship.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementRelationship.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; using JJConsulting.Html.Bootstrap.Models; using JJMasterData.Commons.Data.Entity.Models; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementRelationshipList.cs b/src/MasterData.Core/DataDictionary/Models/FormElementRelationshipList.cs index 36e8e882e..7f6865e95 100644 --- a/src/MasterData.Core/DataDictionary/Models/FormElementRelationshipList.cs +++ b/src/MasterData.Core/DataDictionary/Models/FormElementRelationshipList.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/MasterData.Core/DataDictionary/Models/FormElementRule.cs b/src/MasterData.Core/DataDictionary/Models/FormElementRule.cs new file mode 100644 index 000000000..6278f799a --- /dev/null +++ b/src/MasterData.Core/DataDictionary/Models/FormElementRule.cs @@ -0,0 +1,56 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace JJMasterData.Core.DataDictionary.Models; + +public class FormElementRule +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [Required] + [Display(Name = "Name")] + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + [Display(Name = "Run On Before Insert")] + [JsonPropertyName("runOnBeforeInsert")] + public bool RunOnBeforeInsert { get; set; } = true; + + [Display(Name = "Run On Before Update")] + [JsonPropertyName("runOnBeforeUpdate")] + public bool RunOnBeforeUpdate { get; set; } = true; + + [Display(Name = "Run On Before Import")] + [JsonPropertyName("runOnBeforeImport")] + public bool RunOnBeforeImport { get; set; } = true; + + [Display(Name = "Run On Before Delete")] + [JsonPropertyName("runOnBeforeDelete")] + public bool RunOnBeforeDelete { get; set; } + + [Display(Name = "Rule Type")] + [JsonPropertyName("language")] + public RuleLanguage Language { get; set; } = RuleLanguage.Sql; + + [Display(Name = "Script")] + [JsonPropertyName("script")] + public string Script { get; set; } = string.Empty; + + public bool ShouldRun(PageState pageState) + { + return pageState switch + { + PageState.Insert => RunOnBeforeInsert, + PageState.Update => RunOnBeforeUpdate, + PageState.Import => RunOnBeforeImport, + PageState.Delete => RunOnBeforeDelete, + _ => false + }; + } + + public FormElementRule DeepCopy() + { + return (FormElementRule)MemberwiseClone(); + } +} diff --git a/src/MasterData.Core/DataDictionary/Models/GridUI.cs b/src/MasterData.Core/DataDictionary/Models/GridUI.cs index 86c5af6f3..acd9776f0 100644 --- a/src/MasterData.Core/DataDictionary/Models/GridUI.cs +++ b/src/MasterData.Core/DataDictionary/Models/GridUI.cs @@ -94,12 +94,12 @@ public class GridUI public bool EnableMultiSelect { get; set; } /// - /// Maintains filters, order and grid pagination in the session, + /// Maintains filters, order and grid pagination in cookies, /// and recovers on the first page load. (Default = false) /// /// /// When using this property, we recommend changing the object's [Name] parameter. - /// The [Name] property is used to compose the name of the session variable. + /// The [Name] property is used to compose the cookie names. /// [JsonPropertyName("maintainValuesOnLoad")] [Display(Name = "Save User Preferences")] @@ -166,4 +166,4 @@ public GridUI DeepCopy() { return (GridUI)MemberwiseClone(); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Models/ProcessOptions.cs b/src/MasterData.Core/DataDictionary/Models/ProcessOptions.cs index 89d8b187c..d258c839e 100644 --- a/src/MasterData.Core/DataDictionary/Models/ProcessOptions.cs +++ b/src/MasterData.Core/DataDictionary/Models/ProcessOptions.cs @@ -1,4 +1,3 @@ - using System.Text.Json.Serialization; namespace JJMasterData.Core.DataDictionary.Models; @@ -9,13 +8,13 @@ public class ProcessOptions /// SQL command to be executed before starting the import process /// [JsonPropertyName("commandBeforeProcess")] - public string CommandBeforeProcess { get; set; } + public string? CommandBeforeProcess { get; set; } /// /// SQL command to be executed at the end of the import process /// [JsonPropertyName("commandAfterProcess")] - public string CommandAfterProcess { get; set; } + public string? CommandAfterProcess { get; set; } [JsonPropertyName("scope")] public ProcessScope Scope { get; set; } = ProcessScope.User; diff --git a/src/MasterData.Core/DataDictionary/Models/RuleLanguage.cs b/src/MasterData.Core/DataDictionary/Models/RuleLanguage.cs new file mode 100644 index 000000000..4098b7065 --- /dev/null +++ b/src/MasterData.Core/DataDictionary/Models/RuleLanguage.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace JJMasterData.Core.DataDictionary.Models; + +public enum RuleLanguage +{ + [Display(Name = "SQL")] + Sql = 0, + [Display(Name = "JavaScript")] + JavaScript = 1 +} diff --git a/src/MasterData.Core/DataDictionary/Repository/Abstractions/IDataDictionaryRepository.cs b/src/MasterData.Core/DataDictionary/Repository/Abstractions/IDataDictionaryRepository.cs index 33f17e99e..6205af6ba 100644 --- a/src/MasterData.Core/DataDictionary/Repository/Abstractions/IDataDictionaryRepository.cs +++ b/src/MasterData.Core/DataDictionary/Repository/Abstractions/IDataDictionaryRepository.cs @@ -18,7 +18,7 @@ public interface IDataDictionaryRepository ValueTask> GetElementNameListAsync(); List GetFormElementList(bool? apiSync = null); - Task> GetFormElementInfoListAsync(DataDictionaryFilter filters, OrderByData orderByData, int recordsPerPage, int currentPage); + Task> GetFormElementInfoListAsync(DataDictionaryFilter filters, OrderByData? orderByData, int recordsPerPage, int currentPage); Task ExistsAsync(string elementName); Task InsertOrReplaceAsync(FormElement formElement); Task InsertOrReplaceAsync(IEnumerable formElements); diff --git a/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryOptions.cs b/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryOptions.cs index ab35e8c86..e878f5976 100644 --- a/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryOptions.cs +++ b/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryOptions.cs @@ -1,3 +1,4 @@ +#nullable disable warnings namespace JJMasterData.Core.DataDictionary.Repository; public class FileSystemDataDictionaryOptions diff --git a/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryRepository.cs b/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryRepository.cs index b9c42940e..3af273af2 100644 --- a/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryRepository.cs +++ b/src/MasterData.Core/DataDictionary/Repository/FileSystemDataDictionaryRepository.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/MasterData.Core/DataDictionary/Repository/SqlDataDictionaryRepository.cs b/src/MasterData.Core/DataDictionary/Repository/SqlDataDictionaryRepository.cs index edb2f2f02..2fcb4ec2e 100644 --- a/src/MasterData.Core/DataDictionary/Repository/SqlDataDictionaryRepository.cs +++ b/src/MasterData.Core/DataDictionary/Repository/SqlDataDictionaryRepository.cs @@ -1,4 +1,5 @@ -#nullable enable + +#nullable disable warnings using System; using System.Collections.Generic; using System.Linq; diff --git a/src/MasterData.Core/DataDictionary/Services/ActionsService.cs b/src/MasterData.Core/DataDictionary/Services/ActionsService.cs index 205d80c4c..a85ca250f 100644 --- a/src/MasterData.Core/DataDictionary/Services/ActionsService.cs +++ b/src/MasterData.Core/DataDictionary/Services/ActionsService.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -7,7 +8,6 @@ using JJMasterData.Core.DataDictionary.Models.Actions; using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Expressions.Abstractions; -using JJMasterData.Core.Extensions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.DataDictionary.Services; @@ -19,7 +19,7 @@ public class ActionsService(IValidationDictionary validationDictionary, IEnumerable pluginHandlers) : DataDictionaryServiceBase(validationDictionary, dataDictionaryRepository,stringLocalizer) { - public async Task DeleteActionAsync(string elementName, string actionName, ActionSource context, string fieldName = null) + public async Task DeleteActionAsync(string elementName, string actionName, ActionSource context, string? fieldName = null) { var dicParser = await DataDictionaryRepository.GetFormElementAsync(elementName); DeleteAction(dicParser, actionName, context, fieldName); @@ -28,7 +28,7 @@ public async Task DeleteActionAsync(string elementName, string actionName, return true; } - private static void DeleteAction(FormElement formElement, string originalName, ActionSource context, string fieldName = null) + private static void DeleteAction(FormElement formElement, string originalName, ActionSource context, string? fieldName = null) { if (originalName == null) return; @@ -63,7 +63,7 @@ private static void DeleteAction(FormElement formElement, string originalName, A } } - public async Task SaveAction(string elementName, BasicAction action, ActionSource context, string originalName, string fieldName = null) + public async Task SaveAction(string elementName, BasicAction action, ActionSource context, string? originalName, string? fieldName = null) { var formElement = await DataDictionaryRepository.GetFormElementAsync(elementName); ValidateActionName(formElement, action.Name, originalName, context, fieldName); @@ -111,7 +111,7 @@ public async Task SaveAction(string elementName, BasicAction action, Actio return true; } - private void ValidateActionName(FormElement formElement, string actionName, string originalName, ActionSource context, string fieldName = null) + private void ValidateActionName(FormElement formElement, string actionName, string originalName, ActionSource context, string? fieldName = null) { if (string.IsNullOrWhiteSpace(actionName)) { @@ -149,7 +149,7 @@ private void ValidateActionName(FormElement formElement, string actionName, stri } } - private void ValidateAction(FormElement formElement, BasicAction action, [CanBeNull] string fieldName = null) + private void ValidateAction(FormElement formElement, BasicAction action, [CanBeNull] string? fieldName = null) { if (string.IsNullOrWhiteSpace(action.VisibleExpression)) AddError(nameof(action.VisibleExpression), StringLocalizer["Required [VisibleExpression] field"]); @@ -219,7 +219,7 @@ private void ValidateAction(FormElement formElement, BasicAction action, [CanBeN } } - public async Task SortActionsAsync(string elementName, string[] listAction, ActionSource actionContext, string fieldName) + public async Task SortActionsAsync(string elementName, string[] listAction, ActionSource actionContext, string? fieldName) { var formElement = await DataDictionaryRepository.GetFormElementAsync(elementName); for (int i = 0; i < listAction.Length; i++) diff --git a/src/MasterData.Core/DataDictionary/Services/DataDictionaryLocalizationService.cs b/src/MasterData.Core/DataDictionary/Services/DataDictionaryLocalizationService.cs index fb194985d..5a09c1c6e 100644 --- a/src/MasterData.Core/DataDictionary/Services/DataDictionaryLocalizationService.cs +++ b/src/MasterData.Core/DataDictionary/Services/DataDictionaryLocalizationService.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections; using System.Collections.Generic; @@ -86,7 +84,7 @@ private async Task AddDataItemAsync(HashSet keys, FormElementDataItem? d if (dataItem.HasItems()) { - foreach (var item in dataItem.Items!) + foreach (var item in dataItem.Items) { AddKey(keys, item.Description); } diff --git a/src/MasterData.Core/DataDictionary/Services/DataDictionaryServiceBase.cs b/src/MasterData.Core/DataDictionary/Services/DataDictionaryServiceBase.cs index 6412cc99c..bd0109f1b 100644 --- a/src/MasterData.Core/DataDictionary/Services/DataDictionaryServiceBase.cs +++ b/src/MasterData.Core/DataDictionary/Services/DataDictionaryServiceBase.cs @@ -6,7 +6,6 @@ using JJMasterData.Commons.Validations; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Repository.Abstractions; -using JJMasterData.Core.UI.Components; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.DataDictionary.Services; @@ -91,6 +90,17 @@ public bool ValidateName(string name) return validationDictionary.IsValid; } + protected bool ValidateScriptName(string name, string fieldName = "Name") + { + if (string.IsNullOrWhiteSpace(name)) + { + AddError(fieldName, StringLocalizer["Required [Name] field"]); + return false; + } + + return true; + } + protected static bool ValidateExpression(string value, IEnumerable args) { return args.Any(value.StartsWith); @@ -120,4 +130,4 @@ public async ValueTask> GetElementsDictionaryAsync() return elementList; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Services/ElementExportService.cs b/src/MasterData.Core/DataDictionary/Services/ElementExportService.cs index 104586957..bade5bc61 100644 --- a/src/MasterData.Core/DataDictionary/Services/ElementExportService.cs +++ b/src/MasterData.Core/DataDictionary/Services/ElementExportService.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Collections.Generic; using System.IO; using System.IO.Compression; diff --git a/src/MasterData.Core/DataDictionary/Services/ElementImportService.cs b/src/MasterData.Core/DataDictionary/Services/ElementImportService.cs index 6d1942a29..2426c3b1a 100644 --- a/src/MasterData.Core/DataDictionary/Services/ElementImportService.cs +++ b/src/MasterData.Core/DataDictionary/Services/ElementImportService.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -10,7 +11,7 @@ namespace JJMasterData.Core.DataDictionary.Services; public class ElementImportService(IDataDictionaryRepository dataDictionaryRepository) { - public async Task Import(MemoryStream file) + public async Task Import(Stream file) { file.Seek(0, SeekOrigin.Begin); @@ -20,9 +21,8 @@ public async Task Import(MemoryStream file) return true; } - -#if NET - public async Task ImportZipFile(MemoryStream ms) + + public async Task ImportZipFile(Stream ms) { using var zip = new ZipArchive(ms, ZipArchiveMode.Read, leaveOpen: true); @@ -45,5 +45,4 @@ private static IEnumerable GetFormElements(ZipArchive zip) yield return formElement; } } -#endif -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Services/ElementService.cs b/src/MasterData.Core/DataDictionary/Services/ElementService.cs index 3d3e63e37..44d6f87df 100644 --- a/src/MasterData.Core/DataDictionary/Services/ElementService.cs +++ b/src/MasterData.Core/DataDictionary/Services/ElementService.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Globalization; using System.Threading.Tasks; using JJConsulting.Html; @@ -13,9 +11,6 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataDictionary.Structure; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.Tasks; using JJMasterData.Core.UI.Components; using Microsoft.Extensions.Localization; @@ -164,7 +159,7 @@ await DataDictionaryRepository.GetFormElementInfoListAsync(filter, args.OrderBy, args.TotalOfRecords = result.TotalOfRecords; }; - formView.GridView.OnRenderCellAsync += (_, args) => + formView.GridView.OnRenderCell += (_, args) => { if (args.Field.Name == DataDictionaryStructure.Name) { @@ -195,10 +190,9 @@ await DataDictionaryRepository.GetFormElementInfoListAsync(filter, args.OrderBy, .AppendText(relativeDateFormatter.ToRelativeString(lastModified)); } - return ValueTaskHelper.CompletedTask; }; - formView.GridView.OnRenderActionAsync += (_, args) => + formView.GridView.OnRenderAction += (_, args) => { var elementName = args.FieldValues["name"]?.ToString(); @@ -220,7 +214,6 @@ await DataDictionaryRepository.GetFormElementInfoListAsync(filter, args.OrderBy, break; } - return ValueTaskHelper.CompletedTask; }; return formView; @@ -229,8 +222,8 @@ await DataDictionaryRepository.GetFormElementInfoListAsync(filter, args.OrderBy, #endregion - public Task DeleteAsync(string? elementName) + public Task DeleteAsync(string elementName) { return DataDictionaryRepository.DeleteAsync(elementName); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataDictionary/Services/FieldService.cs b/src/MasterData.Core/DataDictionary/Services/FieldService.cs index 99506d0b6..9498151c8 100644 --- a/src/MasterData.Core/DataDictionary/Services/FieldService.cs +++ b/src/MasterData.Core/DataDictionary/Services/FieldService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using JJMasterData.Commons.Data.Entity.Models; @@ -6,8 +7,6 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Expressions.Abstractions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Tasks; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.DataDictionary.Services; @@ -20,7 +19,7 @@ public class FieldService( IStringLocalizer stringLocalizer) : DataDictionaryServiceBase(validationDictionary, dataDictionaryRepository,stringLocalizer) { - public async Task SaveFieldAsync(string elementName, FormElementField field, string originalName) + public async Task SaveFieldAsync(string elementName, FormElementField field, string? originalName) { var formElement = await DataDictionaryRepository.GetFormElementAsync(elementName); @@ -93,7 +92,7 @@ private static void RemoveUnusedProperties(FormElementField field) } } - private async ValueTask ValidateFieldAsync(FormElement formElement, FormElementField field, string originalName) + private async ValueTask ValidateFieldAsync(FormElement formElement, FormElementField field, string? originalName) { ValidateName(field.Name); @@ -276,7 +275,7 @@ private ValueTask ValidateDataItemAsync(FormElementField field) if (dataItem == null) { AddError("DataItem", StringLocalizer["DataItem cannot be empty."]); - return ValueTaskHelper.CompletedTask; + return ValueTask.CompletedTask; } if (dataItem.DataItemType == DataItemType.SqlCommand) @@ -284,7 +283,7 @@ private ValueTask ValidateDataItemAsync(FormElementField field) if (dataItem.Command == null) { AddError("Command", StringLocalizer["[Command] required"]); - return ValueTaskHelper.CompletedTask; + return ValueTask.CompletedTask; } if (string.IsNullOrEmpty(dataItem.Command.Sql)) @@ -307,7 +306,7 @@ private ValueTask ValidateDataItemAsync(FormElementField field) return ValidateDataElementMapAsync(field); } - return ValueTaskHelper.CompletedTask; + return ValueTask.CompletedTask; } private void ValidateManualItems(List items) diff --git a/src/MasterData.Core/DataDictionary/Services/FormElementRulesService.cs b/src/MasterData.Core/DataDictionary/Services/FormElementRulesService.cs new file mode 100644 index 000000000..f8352f48d --- /dev/null +++ b/src/MasterData.Core/DataDictionary/Services/FormElementRulesService.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataDictionary.Repository.Abstractions; +using Microsoft.Extensions.Localization; + +namespace JJMasterData.Core.DataDictionary.Services; + +public class FormElementRulesService( + IValidationDictionary validationDictionary, + IDataDictionaryRepository dataDictionaryRepository, + IStringLocalizer stringLocalizer) + : DataDictionaryServiceBase(validationDictionary, dataDictionaryRepository, stringLocalizer) +{ + public async Task SaveAsync(string elementName, FormElementRule rule) + { + var formElement = await DataDictionaryRepository.GetFormElementAsync(elementName); + + if (!Validate(rule, formElement)) + return; + + if (rule.Id == 0) + { + rule.Id = formElement.Rules.Count == 0 + ? 1 + : formElement.Rules.Max(v => v.Id) + 1; + + formElement.Rules.Add(rule); + } + else + { + for (var i = 0; i < formElement.Rules.Count; i++) + { + if (formElement.Rules[i].Id != rule.Id) + continue; + + formElement.Rules[i] = rule; + break; + } + } + + await DataDictionaryRepository.InsertOrReplaceAsync(formElement); + } + + public async Task DeleteAsync(string elementName, int ruleId) + { + var formElement = await DataDictionaryRepository.GetFormElementAsync(elementName); + var rule = formElement.Rules.FirstOrDefault(v => v.Id == ruleId); + if (rule == null) + return; + + formElement.Rules.Remove(rule); + await DataDictionaryRepository.InsertOrReplaceAsync(formElement); + } + + public bool Validate(FormElementRule rule, FormElement formElement) + { + ValidateScriptName(rule.Name); + + if (!rule.RunOnBeforeInsert && !rule.RunOnBeforeUpdate && !rule.RunOnBeforeDelete && !rule.RunOnBeforeImport) + AddError(nameof(rule.RunOnBeforeInsert), StringLocalizer["Select at least one operation."]); + + if (string.IsNullOrWhiteSpace(rule.Script)) + AddError(nameof(rule.Script), StringLocalizer["Required [Script] field"]); + + if (formElement.Rules.Any(v => + v.Id != rule.Id && + v.Name.Equals(rule.Name, StringComparison.OrdinalIgnoreCase))) + { + AddError(nameof(rule.Name), StringLocalizer["There is already a rule with this name."]); + } + + return IsValid; + } +} diff --git a/src/MasterData.Core/DataDictionary/Services/PanelService.cs b/src/MasterData.Core/DataDictionary/Services/PanelService.cs index a21bb5d3d..feb781006 100644 --- a/src/MasterData.Core/DataDictionary/Services/PanelService.cs +++ b/src/MasterData.Core/DataDictionary/Services/PanelService.cs @@ -1,11 +1,9 @@ -#nullable enable -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Expressions.Abstractions; -using JJMasterData.Core.Extensions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.DataDictionary.Services; diff --git a/src/MasterData.Core/DataDictionary/Services/RelationshipsService.cs b/src/MasterData.Core/DataDictionary/Services/RelationshipsService.cs index 33cdb0aa0..73d53e268 100644 --- a/src/MasterData.Core/DataDictionary/Services/RelationshipsService.cs +++ b/src/MasterData.Core/DataDictionary/Services/RelationshipsService.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using JJMasterData.Commons.Data.Entity.Models; diff --git a/src/MasterData.Core/DataDictionary/Services/ScriptsService.cs b/src/MasterData.Core/DataDictionary/Services/ScriptsService.cs index fa0c0642c..e7bd4f90b 100644 --- a/src/MasterData.Core/DataDictionary/Services/ScriptsService.cs +++ b/src/MasterData.Core/DataDictionary/Services/ScriptsService.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Collections.Generic; using System.Text; using System.Threading.Tasks; diff --git a/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFilter.cs b/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFilter.cs index 4efda7e15..67205e015 100644 --- a/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFilter.cs +++ b/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFilter.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; diff --git a/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFormElementFactory.cs b/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFormElementFactory.cs index bc39c02d3..6f839acfc 100644 --- a/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFormElementFactory.cs +++ b/src/MasterData.Core/DataDictionary/Structure/DataDictionaryFormElementFactory.cs @@ -1,10 +1,10 @@ +#nullable disable warnings using System.Collections.Generic; using JJConsulting.FontAwesome; using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Core.Configuration.Options; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; diff --git a/src/MasterData.Core/DataDictionary/Structure/DataDictionaryModel.cs b/src/MasterData.Core/DataDictionary/Structure/DataDictionaryModel.cs index c5715bc25..d9c825044 100644 --- a/src/MasterData.Core/DataDictionary/Structure/DataDictionaryModel.cs +++ b/src/MasterData.Core/DataDictionary/Structure/DataDictionaryModel.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using System.Collections.Generic; diff --git a/src/MasterData.Core/DataManager/DataHelper.cs b/src/MasterData.Core/DataManager/DataHelper.cs index 487598f65..62cd96bcc 100644 --- a/src/MasterData.Core/DataManager/DataHelper.cs +++ b/src/MasterData.Core/DataManager/DataHelper.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -257,4 +255,4 @@ public static void RemoveNullValues(Dictionary? values) values.Remove(key); } } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Exportation/Abstractions/DataExportationWriterBase.cs b/src/MasterData.Core/DataManager/Exportation/Abstractions/DataExportationWriterBase.cs index 0e18cd870..051f20d47 100644 --- a/src/MasterData.Core/DataManager/Exportation/Abstractions/DataExportationWriterBase.cs +++ b/src/MasterData.Core/DataManager/Exportation/Abstractions/DataExportationWriterBase.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using System.Collections.Generic; using System.IO; @@ -5,9 +6,10 @@ using System.Threading; using System.Threading.Tasks; using System.Web; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Data.Entity.Repository; using JJMasterData.Commons.Exceptions; -using JJMasterData.Commons.Security.Cryptography.Abstractions; +using JJMasterData.Commons.Storage; using JJMasterData.Commons.Tasks; using JJMasterData.Commons.Tasks.Progress; using JJMasterData.Commons.Util; @@ -15,7 +17,6 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Exportation.Configuration; using JJMasterData.Core.DataManager.Expressions; -using JJMasterData.Core.DataManager.IO; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.UI.Components; using Microsoft.Extensions.Localization; @@ -25,7 +26,6 @@ namespace JJMasterData.Core.DataManager.Exportation.Abstractions; public abstract class DataExportationWriterBase( - IEncryptionService encryptionService, ExpressionsService expressionsService, IStringLocalizer stringLocalizer, IOptionsSnapshot options, @@ -35,27 +35,22 @@ public abstract class DataExportationWriterBase( public event EventHandler OnProgressChanged; protected const int RecordsPerPage = 100000; - + + private List _fields; + #region "Properties" private DataExportationReporter _processReporter; - private List _fields; - private FormFilePathBuilder _pathBuilder; - private IEncryptionService EncryptionService { get; } = encryptionService; private ExpressionsService ExpressionsService { get; } = expressionsService; protected IStringLocalizer StringLocalizer { get; } = stringLocalizer; private IOptionsSnapshot Options { get; } = options; private ILogger Logger { get; } = logger; - private FormFilePathBuilder PathBuilder => _pathBuilder ??= new FormFilePathBuilder(FormElement); - - public string AbsoluteUri { get; internal set; } - private string GetFolderPath(FormElementField field, Dictionary values) - { - return PathBuilder.GetFolderPath(field, values); - } + internal FileDownloaderFactory FileDownloaderFactory { get; set; } + internal IFileStorage FileStorage { get; set; } + internal string AbsoluteUri { get; set; } protected List VisibleFields { @@ -138,41 +133,16 @@ public string FolderPath get { var path = Options.Value.ExportationFolderPath; - string folderPath = DataExportationHelper.GetFolderPath(FormElement, path, UserId); - - CreateFolderPathIfNotExits(folderPath); - - return folderPath; - } - } - - private static void CreateFolderPathIfNotExits(string folderPath) - { - try - { - if (folderPath != null && !Directory.Exists(folderPath)) - Directory.CreateDirectory(folderPath); - } - catch (Exception ex) - { - const string message = "Error on create directory, set a valid ExportationFolderPath on JJMasterData Options."; - throw new JJMasterDataException(message, ex); + return DataExportationHelper.GetExportationFolderPath(FormElement, path, UserId); } } public string UserId { get; set; } -#if NETFRAMEWORK - internal HttpContext HttpContext { get; set; } -#endif - #endregion public async Task RunWorkerAsync(CancellationToken token) { -#if NETFRAMEWORK - HttpContext.Current = HttpContext; -#endif if (FormElement == null) throw new ArgumentNullException(nameof(FormElement)); @@ -185,14 +155,28 @@ public async Task RunWorkerAsync(CancellationToken token) Reporter(ProcessReporter); - var filePath = Path.Combine(FolderPath, GetFilePath()); + var fileName = GetFileName(); + var tempFilePath = Path.GetTempFileName(); - using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite)) + try { - await GenerateDocument(fs, token); + await using (var fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 81920, true)) + { + await GenerateDocument(fs, token); + } + + await using var readStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 81920, true); + var fullPath = FileStoragePath.Combine(FolderPath, fileName); + await FileStorage.SaveAsync(fullPath, readStream, true, token); + } + finally + { + if (File.Exists(tempFilePath)) + File.Delete(tempFilePath); } - ProcessReporter.FilePath = filePath; + ProcessReporter.FolderPath = FolderPath; + ProcessReporter.FileName = fileName; ProcessReporter.EndDate = DateTime.Now; ProcessReporter.HasError = false; @@ -208,14 +192,6 @@ public async Task RunWorkerAsync(CancellationToken token) case ThreadAbortException: ProcessReporter.Message = StringLocalizer["Process aborted by the user."]; break; - case IOException: - if (FileIO.IsFileLocked(FolderPath)) - ProcessReporter.Message = - StringLocalizer[ - "File is already being used by another process. Try downloading it from \"Recently generated files\"."]; - else - goto default; - break; case JJMasterDataException: ProcessReporter.Message = ex.Message; break; @@ -226,8 +202,6 @@ public async Task RunWorkerAsync(CancellationToken token) break; } - if (File.Exists(FolderPath) && !FileIO.IsFileLocked(FolderPath)) - File.Delete(FolderPath); } finally { @@ -243,7 +217,8 @@ protected void Reporter(DataExportationReporter processReporter) public abstract Task GenerateDocument(Stream ms, CancellationToken token); - protected string GetFileLink(FormElementField field, Dictionary row, string value) + protected string GetFileLink(FormElement formElement, FormElementField field, Dictionary row, + string value) { if (!field.DataFile!.ExportAsLink) return null; @@ -255,11 +230,16 @@ protected string GetFileLink(FormElementField field, Dictionary if (files.Length != 1) return null; - var filePath = GetFolderPath(field, row) + value; - return JJFileDownloader.GetExternalDownloadLink(EncryptionService, AbsoluteUri, filePath); + var fileName = Path.GetFileName(files[0]); + if (string.IsNullOrEmpty(fileName)) + return null; + + var downloader = FileDownloaderFactory.Create(formElement, field, row, fileName); + + return new Uri(new Uri(AbsoluteUri), downloader.GetDownloadUrl(AbsoluteUri)).AbsoluteUri; } - private string GetFilePath() + private string GetFileName() { string fileName; var exportActionFileName = FormElement.Options.GridToolbarActions.ExportAction.FileName; @@ -295,4 +275,10 @@ private string GetFilePath() return $"{fileName}_{DateTime.Now:yyyMMdd_HHmmss}.{extension}"; } -} \ No newline at end of file + + public async Task OpenReadAsync() + { + var fullPath = FileStoragePath.Combine(ProcessReporter.FolderPath, ProcessReporter.FileName); + return await FileStorage.OpenReadAsync(fullPath); + } +} diff --git a/src/MasterData.Core/DataManager/Exportation/Abstractions/IExcelWriter.cs b/src/MasterData.Core/DataManager/Exportation/Abstractions/IExcelWriter.cs index 14d021de3..4f021435a 100644 --- a/src/MasterData.Core/DataManager/Exportation/Abstractions/IExcelWriter.cs +++ b/src/MasterData.Core/DataManager/Exportation/Abstractions/IExcelWriter.cs @@ -1,4 +1,4 @@ -using JJMasterData.Commons.Tasks; +using System; using JJMasterData.Core.UI.Events.Args; namespace JJMasterData.Core.DataManager.Exportation.Abstractions; @@ -8,5 +8,5 @@ public interface IExcelWriter : IExportationWriter bool ShowBorder { get; set; } bool ShowRowStriped { get; set; } - event AsyncEventHandler OnRenderCellAsync; + event EventHandler OnRenderCell; } diff --git a/src/MasterData.Core/DataManager/Exportation/Abstractions/IPdfWriter.cs b/src/MasterData.Core/DataManager/Exportation/Abstractions/IPdfWriter.cs index 76430e954..692a54f0f 100644 --- a/src/MasterData.Core/DataManager/Exportation/Abstractions/IPdfWriter.cs +++ b/src/MasterData.Core/DataManager/Exportation/Abstractions/IPdfWriter.cs @@ -1,5 +1,4 @@ using System; -using JJMasterData.Commons.Tasks; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.UI.Events.Args; @@ -8,7 +7,6 @@ namespace JJMasterData.Core.DataManager.Exportation.Abstractions; public interface IPdfWriter : IExportationWriter { event EventHandler OnRenderCell; - event AsyncEventHandler OnRenderCellAsync; public FormElement FormElement { get; set; } public bool ShowBorder { get; set; } @@ -16,4 +14,4 @@ public interface IPdfWriter : IExportationWriter public bool ShowRowStriped { get; set; } public bool IsLandscape { get; set; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Exportation/Abstractions/ITextWriter.cs b/src/MasterData.Core/DataManager/Exportation/Abstractions/ITextWriter.cs index 0ad8fd8ed..12d4709c2 100644 --- a/src/MasterData.Core/DataManager/Exportation/Abstractions/ITextWriter.cs +++ b/src/MasterData.Core/DataManager/Exportation/Abstractions/ITextWriter.cs @@ -1,4 +1,4 @@ -using JJMasterData.Commons.Tasks; +using System; using JJMasterData.Core.UI.Events.Args; namespace JJMasterData.Core.DataManager.Exportation.Abstractions; @@ -6,5 +6,5 @@ namespace JJMasterData.Core.DataManager.Exportation.Abstractions; public interface ITextWriter : IExportationWriter { string Delimiter { get; set; } - event AsyncEventHandler OnRenderCellAsync; -} \ No newline at end of file + event EventHandler OnRenderCell; +} diff --git a/src/MasterData.Core/DataManager/Exportation/Configuration/ExportOptions.cs b/src/MasterData.Core/DataManager/Exportation/Configuration/ExportOptions.cs index 2ca3e1ab6..76bb85763 100644 --- a/src/MasterData.Core/DataManager/Exportation/Configuration/ExportOptions.cs +++ b/src/MasterData.Core/DataManager/Exportation/Configuration/ExportOptions.cs @@ -1,5 +1,5 @@ -using JJMasterData.Commons.Util; -using JJMasterData.Core.Http.Abstractions; +#nullable disable warnings +using JJMasterData.Commons.Util; namespace JJMasterData.Core.DataManager.Exportation.Configuration; @@ -20,16 +20,21 @@ public class ExportOptions public bool IsLandScape { get; set; } = false; public string Delimiter { get; set; } = ";"; - internal static ExportOptions LoadFromForm(IFormValues formValues, string componentName) + internal static ExportOptions LoadFromForm(IHttpContextAccessor httpContextAccessor, string componentName) { var expConfig = new ExportOptions(); - if (formValues[componentName + FileName] != null) + + if (!httpContextAccessor.HttpContext!.Request.HasFormContentType) + return expConfig; + + var form = httpContextAccessor.HttpContext!.Request.Form; + if (form.TryGetValue(componentName + FileName, out var fileName)) { - expConfig.FileExtension = (ExportFileExtension)int.Parse(formValues[componentName + FileName]); - expConfig.IsLandScape = StringManager.ParseBool(formValues[componentName + TableOrientation]); - expConfig.ExportFirstLine = StringManager.ParseBool(formValues[componentName + ExportTableFirstLine]); - expConfig.ExportAllFields = StringManager.ParseBool(formValues[componentName + ExportAll]); - expConfig.Delimiter = formValues[componentName + ExportDelimiter]; + expConfig.FileExtension = (ExportFileExtension)int.Parse(fileName.ToString()); + expConfig.IsLandScape = StringManager.ParseBool(form[componentName + TableOrientation]); + expConfig.ExportFirstLine = StringManager.ParseBool(form[componentName + ExportTableFirstLine]); + expConfig.ExportAllFields = StringManager.ParseBool(form[componentName + ExportAll]); + expConfig.Delimiter = form[componentName + ExportDelimiter]; } return expConfig; diff --git a/src/MasterData.Core/DataManager/Exportation/DataExportationHelper.cs b/src/MasterData.Core/DataManager/Exportation/DataExportationHelper.cs index 04d40b074..efdeefe8a 100644 --- a/src/MasterData.Core/DataManager/Exportation/DataExportationHelper.cs +++ b/src/MasterData.Core/DataManager/Exportation/DataExportationHelper.cs @@ -1,17 +1,15 @@ -#nullable enable - using System.IO; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.UI.Components; namespace JJMasterData.Core.DataManager.Exportation; -internal static class DataExportationHelper +public static class DataExportationHelper { /// /// Path where the files are generated. /// - public static string GetFolderPath(FormElement formElement, string path, string userId) + public static string GetExportationFolderPath(FormElement formElement, string path, string userId) { var processOptions = formElement.Options.GridToolbarActions.ExportAction.ProcessOptions; var folderPath = Path.Combine(path, formElement.Name); @@ -23,9 +21,9 @@ public static string GetFolderPath(FormElement formElement, string path, string return folderPath; } - public static string GetFolderPath(JJDataExportation dataExportation) + public static string GetExportationFolderPath(JJDataExportation dataExportation) { var path = dataExportation.MasterDataOptions.ExportationFolderPath; - return GetFolderPath(dataExportation.FormElement , path, dataExportation.UserId); + return GetExportationFolderPath(dataExportation.FormElement , path, dataExportation.UserId); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Exportation/DataExportationProgressDto.cs b/src/MasterData.Core/DataManager/Exportation/DataExportationProgressDto.cs index 8de89bdc6..63b2d5746 100644 --- a/src/MasterData.Core/DataManager/Exportation/DataExportationProgressDto.cs +++ b/src/MasterData.Core/DataManager/Exportation/DataExportationProgressDto.cs @@ -1,4 +1,5 @@ - +#nullable disable warnings + using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataManager/Exportation/DataExportationReporter.cs b/src/MasterData.Core/DataManager/Exportation/DataExportationReporter.cs index 4d781ecbf..0b7dcf75e 100644 --- a/src/MasterData.Core/DataManager/Exportation/DataExportationReporter.cs +++ b/src/MasterData.Core/DataManager/Exportation/DataExportationReporter.cs @@ -1,33 +1,33 @@ -using System; +#nullable disable warnings +using System; using JJMasterData.Commons.Tasks.Progress; namespace JJMasterData.Core.DataManager.Exportation; public class DataExportationReporter : ProgressReporter { - private int _totalProcessed; public int TotalProcessed { - get => _totalProcessed; + get; set { - _totalProcessed = value; + field = value; UpdatePercentage(); } } - private int _totalOfRecords; public int TotalOfRecords { - get => _totalOfRecords; + get; set { - _totalOfRecords = value; + field = value; UpdatePercentage(); } } - public string FilePath { get; set; } + public string FolderPath { get; set; } + public string FileName { get; set; } private void UpdatePercentage() { diff --git a/src/MasterData.Core/DataManager/Exportation/DataExportationWriterFactory.cs b/src/MasterData.Core/DataManager/Exportation/DataExportationWriterFactory.cs index c6285cd72..ff448a60f 100644 --- a/src/MasterData.Core/DataManager/Exportation/DataExportationWriterFactory.cs +++ b/src/MasterData.Core/DataManager/Exportation/DataExportationWriterFactory.cs @@ -1,6 +1,5 @@ -#nullable enable -using System; -using JJMasterData.Commons.Tasks; +using System; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Core.DataManager.Exportation.Abstractions; using JJMasterData.Core.DataManager.Exportation.Configuration; using JJMasterData.Core.UI.Components; @@ -11,7 +10,7 @@ namespace JJMasterData.Core.DataManager.Exportation; public class DataExportationWriterFactory(IServiceProvider serviceProvider) { - public event AsyncEventHandler? OnRenderCellAsync; + public event EventHandler? OnRenderCell; private IPdfWriter? GetPdfWriter() { @@ -42,7 +41,7 @@ public DataExportationWriterBase GetInstance(JJDataExportation dataExportation) case ExportFileExtension.TXT: var textWriter = GetTextWriter(); textWriter.Delimiter = dataExportation.ExportOptions.Delimiter; - textWriter.OnRenderCellAsync += OnRenderCellAsync; + textWriter.OnRenderCell += OnRenderCell; writer = (DataExportationWriterBase)textWriter; break; @@ -51,7 +50,7 @@ public DataExportationWriterBase GetInstance(JJDataExportation dataExportation) var excelWriter = GetExcelWriter(); excelWriter.ShowRowStriped = dataExportation.ShowRowStriped; excelWriter.ShowBorder = dataExportation.ShowBorder; - excelWriter.OnRenderCellAsync += OnRenderCellAsync; + excelWriter.OnRenderCell += OnRenderCell; writer = (DataExportationWriterBase)excelWriter; @@ -64,7 +63,7 @@ public DataExportationWriterBase GetInstance(JJDataExportation dataExportation) pdfWriter.ShowRowStriped = dataExportation.ShowRowStriped; pdfWriter.ShowBorder = dataExportation.ShowBorder; - pdfWriter.OnRenderCellAsync += OnRenderCellAsync; + pdfWriter.OnRenderCell += OnRenderCell; // ReSharper disable once SuspiciousTypeConversion.Global; // PdfWriter is dynamic loaded by plugin. @@ -81,13 +80,15 @@ public DataExportationWriterBase GetInstance(JJDataExportation dataExportation) return writer; } - private static void ConfigureWriter(JJDataExportation dataExportation, DataExportationWriterBase writer) + private void ConfigureWriter(JJDataExportation dataExportation, DataExportationWriterBase writer) { writer.FormElement = dataExportation.FormElement; writer.Configuration = dataExportation.ExportOptions; writer.UserId = dataExportation.UserId; writer.ProcessOptions = dataExportation.ProcessOptions; - writer.AbsoluteUri = dataExportation.CurrentContext.Request.AbsoluteUri; + writer.FileDownloaderFactory = serviceProvider.GetRequiredService(); + writer.FileStorage = serviceProvider.GetRequiredService(); + writer.AbsoluteUri = dataExportation.HttpContextAccessor.HttpContext!.Request.GetAbsoluteUri(); } diff --git a/src/MasterData.Core/DataManager/Exportation/ExcelWriter.cs b/src/MasterData.Core/DataManager/Exportation/ExcelWriter.cs index dac7327d2..bcc567e60 100644 --- a/src/MasterData.Core/DataManager/Exportation/ExcelWriter.cs +++ b/src/MasterData.Core/DataManager/Exportation/ExcelWriter.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -9,14 +10,11 @@ using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Commons.Data.Entity.Repository; using JJMasterData.Commons.Data.Entity.Repository.Abstractions; -using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Commons.Tasks; using JJMasterData.Core.Configuration.Options; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Exportation.Abstractions; using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.UI.Components; using JJMasterData.Core.UI.Events.Args; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; @@ -27,19 +25,16 @@ namespace JJMasterData.Core.DataManager.Exportation; public class ExcelWriter( ExpressionsService expressionsService, DataItemService dataItemService, - IEncryptionService encryptionService, IStringLocalizer stringLocalizer, IOptionsSnapshot options, ILoggerFactory loggerFactory, IEntityRepository entityRepository) - : DataExportationWriterBase( - encryptionService, - expressionsService, + : DataExportationWriterBase(expressionsService, stringLocalizer, options, loggerFactory.CreateLogger()), IExcelWriter { - public event AsyncEventHandler OnRenderCellAsync; + public event EventHandler OnRenderCell; public bool ShowBorder { get; set; } @@ -175,7 +170,7 @@ private async ValueTask CreateCell(FormElementField field, Dictionary{value}"; else @@ -184,7 +179,7 @@ private async ValueTask CreateCell(FormElementField field, Dictionary CreateCell(FormElementField field, Dictionary"); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Exportation/TextWriter.cs b/src/MasterData.Core/DataManager/Exportation/TextWriter.cs index 1478f06ac..5414c5993 100644 --- a/src/MasterData.Core/DataManager/Exportation/TextWriter.cs +++ b/src/MasterData.Core/DataManager/Exportation/TextWriter.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.IO; using System.Text; using System.Threading; @@ -7,12 +8,9 @@ using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Commons.Data.Entity.Repository; using JJMasterData.Commons.Data.Entity.Repository.Abstractions; -using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Commons.Tasks; using JJMasterData.Core.Configuration.Options; using JJMasterData.Core.DataManager.Exportation.Abstractions; using JJMasterData.Core.DataManager.Expressions; -using JJMasterData.Core.UI.Components; using JJMasterData.Core.UI.Events.Args; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; @@ -21,20 +19,17 @@ namespace JJMasterData.Core.DataManager.Exportation; public class TextWriter( - IEncryptionService encryptionService, - ExpressionsService expressionsService, + ExpressionsService expressionsService, IStringLocalizer stringLocalizer, IOptionsSnapshot options, ILoggerFactory logger, IEntityRepository entityRepository) - : DataExportationWriterBase( - encryptionService, - expressionsService, + : DataExportationWriterBase(expressionsService, stringLocalizer, options, logger.CreateLogger()), ITextWriter { - public event AsyncEventHandler OnRenderCellAsync; + public event EventHandler OnRenderCell; public string Delimiter { get; set; } public override async Task GenerateDocument(Stream stream, CancellationToken token) @@ -114,7 +109,7 @@ private async Task GenerateRows(StreamWriter sw, CancellationToken token) value = cellValue?.ToString(); } - if (OnRenderCellAsync != null) + if (OnRenderCell != null) { var args = new GridCellEventArgs { @@ -123,7 +118,7 @@ private async Task GenerateRows(StreamWriter sw, CancellationToken token) Sender = new JJText(value) }; - await OnRenderCellAsync(this, args); + OnRenderCell(this, args); if(args.HtmlResult != null) value = args.HtmlResult.ToString(); diff --git a/src/MasterData.Core/DataManager/Expressions/Abstractions/IAsyncExpressionProvider.cs b/src/MasterData.Core/DataManager/Expressions/Abstractions/IAsyncExpressionProvider.cs index 1a7670545..b73f60597 100644 --- a/src/MasterData.Core/DataManager/Expressions/Abstractions/IAsyncExpressionProvider.cs +++ b/src/MasterData.Core/DataManager/Expressions/Abstractions/IAsyncExpressionProvider.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/MasterData.Core/DataManager/Expressions/Abstractions/ISyncExpressionProvider.cs b/src/MasterData.Core/DataManager/Expressions/Abstractions/ISyncExpressionProvider.cs index 60a4b8ad1..a66827f47 100644 --- a/src/MasterData.Core/DataManager/Expressions/Abstractions/ISyncExpressionProvider.cs +++ b/src/MasterData.Core/DataManager/Expressions/Abstractions/ISyncExpressionProvider.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Collections.Generic; namespace JJMasterData.Core.DataManager.Expressions.Abstractions; diff --git a/src/MasterData.Core/DataManager/Expressions/ExpressionDataAccessCommandFactory.cs b/src/MasterData.Core/DataManager/Expressions/ExpressionDataAccessCommandFactory.cs index 0ca84311a..948367030 100644 --- a/src/MasterData.Core/DataManager/Expressions/ExpressionDataAccessCommandFactory.cs +++ b/src/MasterData.Core/DataManager/Expressions/ExpressionDataAccessCommandFactory.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; using System.Data; using JJMasterData.Commons.Data; diff --git a/src/MasterData.Core/DataManager/Expressions/ExpressionHelper.cs b/src/MasterData.Core/DataManager/Expressions/ExpressionHelper.cs index 9d92baf86..e6d48778e 100644 --- a/src/MasterData.Core/DataManager/Expressions/ExpressionHelper.cs +++ b/src/MasterData.Core/DataManager/Expressions/ExpressionHelper.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Collections.Generic; using System.Globalization; using System.Text; @@ -15,10 +14,8 @@ public static string ReplaceExpression(string expression, Dictionary doubleValue.ToString("F6", NumberFormatInfo.InvariantInfo), @@ -27,7 +24,7 @@ public static string ReplaceExpression(string expression, Dictionary value?.ToString() ?? string.Empty }; - stringBuilder.Replace($"{Begin}{kvp.Key}{End}", encodeValue ? HttpUtility.HtmlEncode(stringValue) : stringValue); + stringBuilder.Replace($"{Begin}{key}{End}", encodeValue ? HttpUtility.HtmlEncode(stringValue) : stringValue); } return stringBuilder.ToString(); diff --git a/src/MasterData.Core/DataManager/Expressions/ExpressionParser.cs b/src/MasterData.Core/DataManager/Expressions/ExpressionParser.cs index 7574a5eee..99029aa1c 100644 --- a/src/MasterData.Core/DataManager/Expressions/ExpressionParser.cs +++ b/src/MasterData.Core/DataManager/Expressions/ExpressionParser.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Globalization; @@ -8,14 +6,13 @@ using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.Logging; using Microsoft.Extensions.Logging; namespace JJMasterData.Core.DataManager.Expressions; public sealed class ExpressionParser( - IHttpContext httpContext, + IHttpContextAccessor httpContext, IMasterDataUser masterDataUser, ILogger logger) { @@ -68,7 +65,7 @@ public sealed class ExpressionParser( case "isdelete": return pageState is PageState.Delete ? 1 : 0; case "fieldname": - return httpContext.Request.QueryString["fieldName"]; + return httpContext.HttpContext?.Request.Query["fieldName"].ToString(); case "userid": return masterDataUser.Id; case "currentculture": @@ -92,10 +89,6 @@ public sealed class ExpressionParser( else parsedValue = objValue; } - else if (httpContext.Session.HasSession() && httpContext.Session.HasKey(field)) - { - parsedValue = httpContext.Session[field]; - } else { parsedValue = GetClaimValue(field) ?? string.Empty; @@ -106,6 +99,6 @@ public sealed class ExpressionParser( private string? GetClaimValue(string claimType) { - return httpContext.User?.FindFirst(claimType)?.Value; + return httpContext.HttpContext?.User?.FindFirst(claimType)?.Value; } } diff --git a/src/MasterData.Core/DataManager/Expressions/ExpressionsService.cs b/src/MasterData.Core/DataManager/Expressions/ExpressionsService.cs index 5169fa0b5..f56059cd5 100644 --- a/src/MasterData.Core/DataManager/Expressions/ExpressionsService.cs +++ b/src/MasterData.Core/DataManager/Expressions/ExpressionsService.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -11,7 +10,6 @@ using JJMasterData.Core.DataManager.Expressions.Abstractions; using JJMasterData.Core.DataManager.Expressions.Providers; using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Extensions; using JJMasterData.Core.Logging; using Microsoft.Extensions.Logging; @@ -58,7 +56,7 @@ private void EncryptValues(Dictionary parsedValues) foreach (var key in keysToUpdate) { - parsedValues[key] = encryptionService.EncryptStringWithUrlEscape(parsedValues[key]!.ToString()!); + parsedValues[key] = encryptionService.EncryptString(parsedValues[key]!.ToString()!); } } diff --git a/src/MasterData.Core/DataManager/Expressions/Providers/DefaultExpressionProvider.cs b/src/MasterData.Core/DataManager/Expressions/Providers/DefaultExpressionProvider.cs index 5bfca3ecd..461031356 100644 --- a/src/MasterData.Core/DataManager/Expressions/Providers/DefaultExpressionProvider.cs +++ b/src/MasterData.Core/DataManager/Expressions/Providers/DefaultExpressionProvider.cs @@ -1,8 +1,5 @@ -#nullable enable - using System; using System.Collections.Generic; -using System.Globalization; using System.Threading.Tasks; using JJMasterData.Core.Configuration.Options; using JJMasterData.Core.DataManager.Expressions.Abstractions; @@ -11,6 +8,7 @@ using Microsoft.Extensions.Options; using NCalc; using NCalc.Factories; +using NCalc.Handlers; namespace JJMasterData.Core.DataManager.Expressions.Providers; @@ -21,14 +19,6 @@ public sealed class DefaultExpressionProvider( ILogger logger) : ISyncExpressionProvider, IAsyncExpressionProvider { - private readonly ExpressionContext _expressionContext = options.Value.ExpressionContext with - { - StaticParameters = new Dictionary(options.Value.ExpressionContext.StaticParameters, StringComparer.InvariantCultureIgnoreCase) - { - ["ServiceProvider"] = serviceProvider - } - }; - public string Prefix => "exp"; public string Title => "Expression"; @@ -38,11 +28,16 @@ public sealed class DefaultExpressionProvider( { var parameters = new Dictionary(parsedValues.Count, StringComparer.InvariantCultureIgnoreCase); var preparedExpression = PrepareExpressionWithParameters(expression, parsedValues, parameters); + + var expressionContext = new ExpressionContext(options.Value.ExpressionContext) + { + Parameters = new Dictionary(parameters, StringComparer.InvariantCultureIgnoreCase) + { + ["ServiceProvider"] = serviceProvider + } + }; - foreach (var parameter in parameters) - _expressionContext.StaticParameters[parameter.Key] = parameter.Value; - - var ncalcExpression = expressionFactory.Create(preparedExpression, _expressionContext); + var ncalcExpression = expressionFactory.Create(preparedExpression, options.Value.ExpressionConfiguration, expressionContext); logger.LogExpression(preparedExpression); diff --git a/src/MasterData.Core/DataManager/Expressions/Providers/SqlExpressionProvider.cs b/src/MasterData.Core/DataManager/Expressions/Providers/SqlExpressionProvider.cs index e88ce19f0..4d2186d3f 100644 --- a/src/MasterData.Core/DataManager/Expressions/Providers/SqlExpressionProvider.cs +++ b/src/MasterData.Core/DataManager/Expressions/Providers/SqlExpressionProvider.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/MasterData.Core/DataManager/Expressions/Providers/ValueExpressionProvider.cs b/src/MasterData.Core/DataManager/Expressions/Providers/ValueExpressionProvider.cs index 32e338ae6..2cfb75e7a 100644 --- a/src/MasterData.Core/DataManager/Expressions/Providers/ValueExpressionProvider.cs +++ b/src/MasterData.Core/DataManager/Expressions/Providers/ValueExpressionProvider.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -16,7 +15,7 @@ public sealed class ValueExpressionProvider : IAsyncExpressionProvider, ISyncExp public string Title => "Value"; public object Evaluate(string expression, Dictionary parsedValues) { - if (expression.Contains(ExpressionHelper.Begin.ToString())) + if (expression.Contains(ExpressionHelper.Begin)) return ExpressionHelper.ReplaceExpression(expression, parsedValues).Trim(); return expression.Trim(); diff --git a/src/MasterData.Core/DataManager/FontAwesomeIconHelper.cs b/src/MasterData.Core/DataManager/FontAwesomeIconHelper.cs index 20dd8e972..c22c6fb98 100644 --- a/src/MasterData.Core/DataManager/FontAwesomeIconHelper.cs +++ b/src/MasterData.Core/DataManager/FontAwesomeIconHelper.cs @@ -1,4 +1,3 @@ -#nullable enable using JJConsulting.FontAwesome; using JJMasterData.Commons.Exceptions; using JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/DataManager/IO/FormFileContent.cs b/src/MasterData.Core/DataManager/IO/FormFileContent.cs deleted file mode 100644 index 47a75d536..000000000 --- a/src/MasterData.Core/DataManager/IO/FormFileContent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace JJMasterData.Core.DataManager.IO; - -public class FormFileContent -{ - public string FileName { get; set; } - public byte[] Bytes { get; init; } - public long Length { get; set;} - public DateTime LastWriteTime { get; set; } -} \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/IO/FormFileManager.cs b/src/MasterData.Core/DataManager/IO/FormFileManager.cs deleted file mode 100644 index a3211bcc6..000000000 --- a/src/MasterData.Core/DataManager/IO/FormFileManager.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using JJMasterData.Commons.Exceptions; -using JJMasterData.Commons.Util; -using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.UI.Events.Args; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; - -namespace JJMasterData.Core.DataManager.IO; - -public class FormFileManager(string memoryFilesSessionName, - IHttpContext httpContext, - IStringLocalizer stringLocalizer, - ILogger logger) -{ - public event EventHandler OnBeforeCreateFile; - public event EventHandler OnBeforeDeleteFile; - public event EventHandler OnBeforeRenameFile; - - /// - /// Session variable name - /// - private string MemoryFilesSessionName { get; } = $"{memoryFilesSessionName}_files"; - - /// - /// Always apply changes from files on disk, - /// if it is false, keep it in memory - /// Default: true - /// - public bool AutoSave { get; set; } = true; - - /// - /// Full Directory Path. - /// (Optional) If the path is not given, all files will be stored in the session. - /// - /// - /// The path is OS agnostic, you can use for example C:\Temp\Files\ or /home/gumbarros/Documents/Files, - /// but beware where you're deploying your application. - /// - public string FolderPath { get; set; } - - public List MemoryFiles - { - get => httpContext.Session.GetSessionValue>(MemoryFilesSessionName); - set => httpContext.Session.SetSessionValue(MemoryFilesSessionName, value); - } - - public List GetFiles() - { - List files = null; - - if (!AutoSave || string.IsNullOrEmpty(FolderPath)) - files = MemoryFiles; - - return files ?? GetPhysicalFiles(); - } - - public void RenameFile(string currentName, string newName) - { - if (string.IsNullOrEmpty(currentName)) - throw new ArgumentNullException(nameof(currentName)); - - if (string.IsNullOrWhiteSpace(newName)) - throw new ArgumentNullException(stringLocalizer["Required file name"]); - - if (!FileIO.GetFileNameExtension(currentName).Equals(FileIO.GetFileNameExtension(newName))) - throw new JJMasterDataException(stringLocalizer["The file extension must remain the same"]); - - var files = GetFiles(); - if (files.Exists(x => x.Content.FileName.Equals(newName))) - throw new JJMasterDataException(stringLocalizer["A file with the name {0} already exists", newName]); - - if (OnBeforeRenameFile != null) - { - var args = new FormRenameFileEventArgs(currentName, newName); - OnBeforeRenameFile.Invoke(this, args); - - if (!string.IsNullOrEmpty(args.ErrorMessage)) - throw new JJMasterDataException(args.ErrorMessage); - } - - if (AutoSave && !string.IsNullOrEmpty(FolderPath)) - { - File.Move(Path.Combine(FolderPath,currentName), Path.Combine(FolderPath, newName)); - } - else - { - var file = files.Find(x => x.Content.FileName.Equals(currentName)); - if (file == null) - throw new JJMasterDataException(stringLocalizer["file {0} not found!", currentName]); - - files.Remove(file); - - file.Content.FileName = newName; - file.OldName ??= currentName; - - file.IsRenamed = true; - files.Add(file); - - MemoryFiles = files; - } - } - - public FormFileInfo GetFile(string fileName) - { - var files = GetFiles(); - var file = files.Find(x => fileName.Equals(x.Content.FileName) || fileName.Equals(x.OldName)); - - return file; - } - - public string GetFilePath(string fileName) - { - return Path.Combine(FolderPath, fileName); - } - - public void CreateFile(FormFileContent fileContent, bool replaceIfExists) - { - if (fileContent == null) - throw new ArgumentNullException(nameof(fileContent)); - - string fileName = fileContent.FileName; - - if (OnBeforeCreateFile != null) - { - var args = new FormUploadFileEventArgs(fileContent); - OnBeforeCreateFile.Invoke(this, args); - string errorMessage = args.ErrorMessage; - - if (!string.IsNullOrEmpty(errorMessage)) - { - var exception = new JJMasterDataException(errorMessage); - logger.LogError(exception,"Error OnBeforeCreateFile"); - throw exception; - } - - } - - if (replaceIfExists && CountFiles() > 0) - DeleteAll(); - - if (fileName?.LastIndexOf("\\") > 0) - // ReSharper disable once ReplaceSubstringWithRangeIndexer - fileName = fileName.Substring(fileName.LastIndexOf("\\", StringComparison.Ordinal) + 1); - - if (AutoSave && !string.IsNullOrEmpty(FolderPath)) - { - SavePhysicalFile(fileContent); - } - else - { - var files = GetFiles(); - var currentFile = files.Find(x => x.Content.FileName.Equals(fileName)); - if (currentFile == null) - { - var file = new FormFileInfo - { - Content = fileContent - }; - files.Add(file); - } - else - { - currentFile.Content = fileContent; - currentFile.Deleted = false; - } - - MemoryFiles = files; - } - } - - public void DeleteFile(string fileName) - { - if (OnBeforeDeleteFile != null) - { - var args = new FormDeleteFileEventArgs(fileName); - OnBeforeDeleteFile.Invoke(this, args); - - if (!string.IsNullOrEmpty(args.ErrorMessage)) - { - var exception = new JJMasterDataException(args.ErrorMessage); - logger.LogError(exception, "Error OnBeforeDeleteFile"); - throw exception; - } - } - - if (AutoSave && !string.IsNullOrEmpty(FolderPath)) - { - File.Delete(Path.Combine(FolderPath, fileName)); - } - else - { - var files = GetFiles(); - var file = files.Find(x => x.Content.FileName.Equals(fileName)); - if (file != null) - { - if (!file.IsInMemory) - file.Deleted = true; - else - files.Remove(file); - } - - MemoryFiles = files; - } - } - - public void DeleteAll() - { - if (!string.IsNullOrEmpty(FolderPath)) - { - if (Directory.Exists(FolderPath)) - Directory.Delete(FolderPath, true); - } - - MemoryFiles = null; - } - - public int CountFiles() - { - var listFiles = GetFiles(); - return listFiles.Count(x => !x.Deleted); - } - - public void SaveMemoryFiles(string folderPath, bool deleteExistingFiles = false) - { - if (string.IsNullOrEmpty(folderPath)) - throw new ArgumentNullException(nameof(folderPath)); - - if (MemoryFiles == null) - return; - - if (!Directory.Exists(folderPath)) - Directory.CreateDirectory(folderPath); - - FolderPath = folderPath; - - if (deleteExistingFiles) - { - foreach (var filePath in Directory.GetFiles(FolderPath)) - File.Delete(filePath); - } - - foreach (var file in MemoryFiles) - { - string fileName = file.Content.FileName; - if (file.Deleted) - { - string filename = string.IsNullOrEmpty(file.OldName) ? fileName : file.OldName; - File.Delete(folderPath + filename); - } - else if (!string.IsNullOrEmpty(file.OldName) && !file.IsInMemory) - { - File.Move(folderPath + file.OldName, folderPath + fileName); - } - else if (file.Content.Bytes != null && file.IsInMemory) - { - SavePhysicalFile(file.Content); - } - } - - MemoryFiles = null; - } - - private List GetPhysicalFiles() - { - var formFileInfoList = new List(); - if (string.IsNullOrEmpty(FolderPath)) - return formFileInfoList; - - var directory = new DirectoryInfo(FolderPath); - if (directory.Exists) - { - var files = directory.GetFiles(); - foreach (var file in files) - { - formFileInfoList.Add(new FormFileInfo - { - Content = - { - FileName = file.Name, - Length = file.Length, - LastWriteTime = file.LastWriteTime, - } - }); - } - } - return formFileInfoList; - } - - private void SavePhysicalFile(FormFileContent file) - { - if (file == null) - throw new ArgumentNullException(nameof(file)); - - if (string.IsNullOrEmpty(FolderPath)) - throw new ArgumentNullException(nameof(FolderPath)); - - if (!Directory.Exists(FolderPath)) - Directory.CreateDirectory(FolderPath); - - var fileFullName = Path.Combine(FolderPath, file.FileName); - using var ms = new MemoryStream(file.Bytes); - using var fileStream = File.Create(fileFullName); - ms.Seek(0, SeekOrigin.Begin); - ms.CopyTo(fileStream); - fileStream.Close(); - } -} diff --git a/src/MasterData.Core/DataManager/IO/FormFileManagerFactory.cs b/src/MasterData.Core/DataManager/IO/FormFileManagerFactory.cs deleted file mode 100644 index e578a07a9..000000000 --- a/src/MasterData.Core/DataManager/IO/FormFileManagerFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -using JJMasterData.Core.Http.Abstractions; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; - -namespace JJMasterData.Core.DataManager.IO; - -public class FormFileManagerFactory(IHttpContext httpContext, IStringLocalizer stringLocalizer, ILoggerFactory loggerFactory) -{ - - public FormFileManager Create(string memoryFilesSessionName) - { - return new FormFileManager(memoryFilesSessionName, httpContext, stringLocalizer, - loggerFactory.CreateLogger()); - } -} \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/IO/FormFilePathBuilder.cs b/src/MasterData.Core/DataManager/IO/FormFilePathBuilder.cs deleted file mode 100644 index b2e42409d..000000000 --- a/src/MasterData.Core/DataManager/IO/FormFilePathBuilder.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using JJMasterData.Commons.Util; -using JJMasterData.Core.DataDictionary.Models; - -namespace JJMasterData.Core.DataManager.IO; - -public class FormFilePathBuilder(FormElement formElement) -{ - public string GetFolderPath(FormElementField field, Dictionary formValues) - { - if (field.DataFile == null) - throw new ArgumentException(@$"{nameof(FormElementField.DataFile)} not defined.", field.Name); - - //Pks concat with underline - var pkValues = DataHelper.ParsePkValues(formElement, formValues, '_'); - - //Path configured in the dictionary - var path = field.DataFile.FolderPath; - - if (string.IsNullOrEmpty(path)) - throw new ArgumentException(@$"{nameof(FormElementField.DataFile.FolderPath)} cannot be empty.", field.Name); - - var separator = Path.DirectorySeparatorChar; - - if (path.Contains("{app.path}")) - { - var appPath = FileIO.GetApplicationPath().TrimEnd(separator); - - path = path.Replace("{app.path}", appPath); - } - - path = Path.Combine(path, pkValues); - - if (!path.EndsWith(separator.ToString())) - path += separator; - - return path; - } -} diff --git a/src/MasterData.Core/DataManager/IO/FormFileService.cs b/src/MasterData.Core/DataManager/IO/FormFileService.cs deleted file mode 100644 index 70b96b9ee..000000000 --- a/src/MasterData.Core/DataManager/IO/FormFileService.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using JJMasterData.Core.DataDictionary.Models; - -namespace JJMasterData.Core.DataManager.IO; - -public class FormFileService(FormFileManagerFactory formFileManagerFactory) -{ - public void SaveFormMemoryFiles(FormElement formElement, Dictionary primaryKeys) - { - var uploadFields = formElement.Fields.FindAll(x => x.Component == FormComponent.File); - if (uploadFields.Count == 0) - return; - - var pathBuilder = new FormFilePathBuilder(formElement); - foreach (var field in uploadFields) - { - var folderPath = pathBuilder.GetFolderPath(field, primaryKeys); - var manager = formFileManagerFactory.Create($"{field.Name}-upload-view-files"); - - manager.SaveMemoryFiles(folderPath, deleteExistingFiles: !field.DataFile.MultipleFile); - } - } - - public void DeleteFiles(FormElement formElement, Dictionary primaryKeys) - { - var fileFields = formElement.Fields.FindAll(x => x.Component == FormComponent.File); - if (fileFields.Count == 0) - return; - - foreach (var field in fileFields) - { - var manager = formFileManagerFactory.Create($"{field.Name}-upload-view-files"); - manager.FolderPath = new FormFilePathBuilder(formElement).GetFolderPath(field, primaryKeys); - manager.DeleteAll(); - } - } -} \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/Importation/DataImportationDto.cs b/src/MasterData.Core/DataManager/Importation/DataImportationDto.cs index 51f9263c5..ce425bcc6 100644 --- a/src/MasterData.Core/DataManager/Importation/DataImportationDto.cs +++ b/src/MasterData.Core/DataManager/Importation/DataImportationDto.cs @@ -1,4 +1,5 @@ - +#nullable disable warnings + using System.Text.Json.Serialization; diff --git a/src/MasterData.Core/DataManager/Importation/DataImportationWorker.cs b/src/MasterData.Core/DataManager/Importation/DataImportationWorker.cs index 829b649a5..06d6951ce 100644 --- a/src/MasterData.Core/DataManager/Importation/DataImportationWorker.cs +++ b/src/MasterData.Core/DataManager/Importation/DataImportationWorker.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Globalization; using System.Text; @@ -66,14 +67,8 @@ public class DataImportationWorker( internal FormService FormService { get; } = formService; -#if NETFRAMEWORK - private System.Web.HttpContext HttpContext { get; } = System.Web.HttpContext.Current; -#endif public async Task RunWorkerAsync(CancellationToken token) { -#if NETFRAMEWORK - System.Web.HttpContext.Current = HttpContext; -#endif var currentProcess = new DataImportationReporter(StringLocalizer); try { @@ -308,4 +303,4 @@ private async Task> SaveRowValues(Dictionary coreOptions) : IMasterDataUser { - public string Id { get; set; } = httpContext.User?.GetUserId(coreOptions.Value.UserIdClaimType); + public string Id { get; set; } = httpContext.HttpContext?.User.GetUserId(coreOptions.Value.UserIdClaimType); } \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/Models/DataContext.cs b/src/MasterData.Core/DataManager/Models/DataContext.cs index 6414e38da..1795f9efc 100644 --- a/src/MasterData.Core/DataManager/Models/DataContext.cs +++ b/src/MasterData.Core/DataManager/Models/DataContext.cs @@ -1,8 +1,4 @@ -#nullable enable - -using JJMasterData.Core.Http.Abstractions; - -namespace JJMasterData.Core.DataManager.Models; +namespace JJMasterData.Core.DataManager.Models; public class DataContext { @@ -18,11 +14,16 @@ public DataContext() { } - public DataContext(IHttpRequest request, DataContextSource source, string? userId) + public DataContext(IHttpContextAccessor request, DataContextSource source, string? userId) + : this(request.HttpContext?.Request, source, userId) + { + } + + public DataContext(HttpRequest? request, DataContextSource source, string? userId) { Source = source; UserId = userId; - IpAddress = request.UserHostAddress; - BrowserInfo = request.UserAgent; + IpAddress = request?.HttpContext.Connection.RemoteIpAddress?.ToString(); + BrowserInfo = request?.Headers.UserAgent.ToString(); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Models/DataItemResult.cs b/src/MasterData.Core/DataManager/Models/DataItemResult.cs index b5050ffc8..bce00c602 100644 --- a/src/MasterData.Core/DataManager/Models/DataItemResult.cs +++ b/src/MasterData.Core/DataManager/Models/DataItemResult.cs @@ -1,7 +1,4 @@ -#nullable enable - - -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace JJMasterData.Core.DataManager.Models; diff --git a/src/MasterData.Core/DataManager/Models/DataQuery.cs b/src/MasterData.Core/DataManager/Models/DataQuery.cs index cc780f1b9..1cccf51a4 100644 --- a/src/MasterData.Core/DataManager/Models/DataQuery.cs +++ b/src/MasterData.Core/DataManager/Models/DataQuery.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; namespace JJMasterData.Core.DataManager.Models; diff --git a/src/MasterData.Core/DataManager/Models/FormFileInfo.cs b/src/MasterData.Core/DataManager/Models/FormFileInfo.cs deleted file mode 100644 index 361bb137b..000000000 --- a/src/MasterData.Core/DataManager/Models/FormFileInfo.cs +++ /dev/null @@ -1,27 +0,0 @@ -using JJMasterData.Core.DataManager.IO; - -namespace JJMasterData.Core.DataManager.Models; - -public class FormFileInfo -{ - private FormFileContent _content; - - public FormFileContent Content - { - get => _content ??= new FormFileContent(); - set => _content = value; - } - - public FormFileInfo() - { - - } - public bool IsRenamed { get; set; } - public bool Deleted { get; set; } - - public string OldName { get; set; } - - public string FileName => Content.FileName ?? OldName; - - public bool IsInMemory => Content.Bytes != null; -} diff --git a/src/MasterData.Core/DataManager/Models/FormLetter.cs b/src/MasterData.Core/DataManager/Models/FormLetter.cs index 0bad08e9d..d042c8b1e 100644 --- a/src/MasterData.Core/DataManager/Models/FormLetter.cs +++ b/src/MasterData.Core/DataManager/Models/FormLetter.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.Collections.Generic; namespace JJMasterData.Core.DataManager.Models; diff --git a/src/MasterData.Core/DataManager/Models/FormStateData.cs b/src/MasterData.Core/DataManager/Models/FormStateData.cs index 508778aaa..bc21ac382 100644 --- a/src/MasterData.Core/DataManager/Models/FormStateData.cs +++ b/src/MasterData.Core/DataManager/Models/FormStateData.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.Collections.Generic; +using System.Collections.Generic; using JJMasterData.Core.DataDictionary.Models; namespace JJMasterData.Core.DataManager.Models; diff --git a/src/MasterData.Core/DataManager/Models/UrlRedirectModel.cs b/src/MasterData.Core/DataManager/Models/UrlRedirectModel.cs index f00e8aacf..6e5d3207f 100644 --- a/src/MasterData.Core/DataManager/Models/UrlRedirectModel.cs +++ b/src/MasterData.Core/DataManager/Models/UrlRedirectModel.cs @@ -1,8 +1,5 @@ -#nullable enable - using System.Text.Json.Serialization; using JJConsulting.Html.Bootstrap.Models; -using JJMasterData.Core.DataDictionary.Models; namespace JJMasterData.Core.DataManager.Models; diff --git a/src/MasterData.Core/DataManager/Services/Abstractions/IRuleExecutor.cs b/src/MasterData.Core/DataManager/Services/Abstractions/IRuleExecutor.cs new file mode 100644 index 000000000..401ea387e --- /dev/null +++ b/src/MasterData.Core/DataManager/Services/Abstractions/IRuleExecutor.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JJMasterData.Core.DataDictionary.Models; + +namespace JJMasterData.Core.DataManager.Services.Abstractions; + +public interface IRuleExecutor +{ + RuleLanguage Language { get; } + + Task> ExecuteAsync( + FormElement formElement, + FormElementRule rule, + Dictionary values); +} diff --git a/src/MasterData.Core/DataManager/Services/AuditLogService.cs b/src/MasterData.Core/DataManager/Services/AuditLogService.cs index b4e79edac..4b80e95cf 100644 --- a/src/MasterData.Core/DataManager/Services/AuditLogService.cs +++ b/src/MasterData.Core/DataManager/Services/AuditLogService.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -32,7 +33,7 @@ public class AuditLogService( public const string DicBrowser = "browser"; public const string DicJson = "json"; - public async Task LogAsync(Element element,DataContext dataContext, Dictionary formValues, CommandOperation action) + public async Task LogAsync(Element element,DataContext dataContext, Dictionary formValues, CommandOperation action) { var values = new Dictionary { diff --git a/src/MasterData.Core/DataManager/Services/DataItemService.cs b/src/MasterData.Core/DataManager/Services/DataItemService.cs index 6aaab04ab..1b5404c36 100644 --- a/src/MasterData.Core/DataManager/Services/DataItemService.cs +++ b/src/MasterData.Core/DataManager/Services/DataItemService.cs @@ -1,5 +1,4 @@ -#nullable enable - +#nullable disable warnings using System; using System.Collections.Generic; using System.Data; diff --git a/src/MasterData.Core/DataManager/Services/ElementFileService.cs b/src/MasterData.Core/DataManager/Services/ElementFileService.cs index ad9d7fd6a..c7d9004be 100644 --- a/src/MasterData.Core/DataManager/Services/ElementFileService.cs +++ b/src/MasterData.Core/DataManager/Services/ElementFileService.cs @@ -1,46 +1,68 @@ -#if NET - -#nullable enable using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Commons.Data.Entity.Repository.Abstractions; +using JJMasterData.Commons.Storage; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Repository.Abstractions; -using JJMasterData.Core.DataManager.IO; -using Microsoft.AspNetCore.Http; namespace JJMasterData.Core.DataManager.Services; -public class ElementFileService(IDataDictionaryRepository dictionaryRepository, IEntityRepository entityRepository) +public class ElementFileService( + IDataDictionaryRepository dictionaryRepository, + IEntityRepository entityRepository, + IFileStorage fileStorage, + FileValidationService fileValidationService) { - public async Task GetElementFileAsync(string elementName, string pkValues, string fieldName, string? fileName) + public async Task SaveFileAsync(string folderPath, IFormFile file, bool overwrite = true, string? allowedTypes = null) { - var formElement = await dictionaryRepository.GetFormElementAsync(elementName); + var fileName = Path.GetFileName(file.FileName); + fileValidationService.Validate(file, allowedTypes); + var fullPath = FileStoragePath.Combine(folderPath, fileName); + await using var uploadStream = file.OpenReadStream(); + await fileStorage.SaveAsync(fullPath, uploadStream, overwrite); + } + + public async Task DeleteFileAsync(string folderPath, string fileName) + { fileName = Path.GetFileName(fileName); + var fullPath = FileStoragePath.Combine(folderPath, fileName); + await fileStorage.DeleteAsync(fullPath); + } - var field = formElement.Fields.First(f => f.Name == fieldName); + public async Task RenameFileAsync(string folderPath, string oldName, string newName) + { + oldName = Path.GetFileName(oldName); + newName = Path.GetFileName(newName); + fileValidationService.ValidateFileName(newName); - var builder = new FormFilePathBuilder(formElement); + var oldFullPath = FileStoragePath.Combine(folderPath, oldName); + var newFullPath = FileStoragePath.Combine(folderPath, newName); + await fileStorage.MoveAsync(oldFullPath, newFullPath); + } - var path = builder.GetFolderPath(field, DataHelper.GetPkValues(formElement, pkValues, ',')); + public async Task GetElementFileAsync(string elementName, string pkValues, string fieldName, string? fileName) + { + var formElement = await dictionaryRepository.GetFormElementAsync(elementName); + + fileName = Path.GetFileName(fileName); + + var field = formElement.Fields.First(f => f.Name == fieldName); + var folderPath = FileStoragePath.GetFolderPath(formElement, field, DataHelper.GetPkValues(formElement, pkValues, ',')!); - string? file; if (string.IsNullOrEmpty(fileName)) - file = Directory.GetFiles(path).FirstOrDefault(); - else - file = Directory.GetFiles(path).FirstOrDefault(f => f.EndsWith(fileName)); + fileName = (await fileStorage.ListAsync(folderPath)).FirstOrDefault()?.FileName; - if (file == null) + if (string.IsNullOrEmpty(fileName)) return null; - var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); - - return fileStream; + var fullPath = FileStoragePath.Combine(folderPath, fileName); + return await fileStorage.OpenReadAsync(fullPath); } @@ -56,6 +78,7 @@ public async Task SetElementFileAsync( throw new UnauthorizedAccessException(); var field = formElement.Fields.First(f => f.Name == fieldName); + fileValidationService.Validate(file, field.DataFile?.AllowedTypes); await SetPhysicalFileAsync(formElement, field, pkValues, file); @@ -96,38 +119,16 @@ private async Task SetEntityFileAsync(FormElement formElement, FormElementField await entityRepository.SetValuesAsync(formElement, values); } - private static async Task SetPhysicalFileAsync( + private async Task SetPhysicalFileAsync( FormElement formElement, FormElementField field, string pkValues, IFormFile file) { - var builder = new FormFilePathBuilder(formElement); - var hashValues = DataHelper.GetPkValues(formElement, pkValues, ','); - - var path = builder.GetFolderPath(field, hashValues); - - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); + var folderPath = FileStoragePath.GetFolderPath(formElement, field, hashValues!); - var fileName = Path.GetFileName(file.FileName); - - if (field.DataFile!.MultipleFile) - { - foreach (var fileInfo in new DirectoryInfo(path).EnumerateFiles()) - { - if (fileInfo.Name == fileName) - { - fileInfo.Delete(); - } - } - } - - await using var fileStream = - new FileStream(Path.Combine(path, fileName), FileMode.OpenOrCreate, FileAccess.ReadWrite); - - await file.CopyToAsync(fileStream); + await SaveFileAsync(folderPath, file, true, field.DataFile?.AllowedTypes); } public async Task DeleteFileAsync(string elementName, string fieldName, string pkValues, string fileName) @@ -141,24 +142,16 @@ public async Task DeleteFileAsync(string elementName, string fieldName, string p fileName = Path.GetFileName(fileName); - DeletePhysicalFile(formElement, field, pkValues, fileName); + await DeletePhysicalFileAsync(formElement, field, pkValues, fileName); await DeleteEntityFileAsync(formElement, field, pkValues, fileName); } - private static void DeletePhysicalFile(FormElement formElement, FormElementField field, string pkValues, string fileName) + private async Task DeletePhysicalFileAsync(FormElement formElement, FormElementField field, string pkValues, string fileName) { - var builder = new FormFilePathBuilder(formElement); - - var path = builder.GetFolderPath(field, DataHelper.GetPkValues(formElement, pkValues, ',')); - fileName = Path.GetFileName(fileName); - - var filePath = Path.Combine(path, fileName); - - if (File.Exists(filePath)) - File.Delete(filePath); - else - throw new KeyNotFoundException("File not found"); + var folderPath = FileStoragePath.GetFolderPath(formElement, field, DataHelper.GetPkValues(formElement, pkValues, ',')!); + + await DeleteFileAsync(folderPath, fileName); } private async Task DeleteEntityFileAsync(Element element, FormElementField field, string pkValues, string fileName) @@ -173,8 +166,9 @@ private async Task DeleteEntityFileAsync(Element element, FormElementField field if (field.DataFile!.MultipleFile) { var currentFiles = values[field.Name]!.ToString()!.Split(',').ToList(); - - if (currentFiles.Contains(fileName)) + + var removed = currentFiles.Remove(fileName); + if (removed) { currentFiles.Remove(fileName); values[field.Name] = string.Join(",", currentFiles); @@ -201,23 +195,14 @@ public async Task RenameFileAsync(string elementName, string fieldName, string p oldName = Path.GetFileName(oldName); newName = Path.GetFileName(newName); - RenamePhysicalFile(formElement, field, pkValues, oldName, newName); + await RenamePhysicalFileAsync(formElement, field, pkValues, oldName, newName); await RenameEntityFileAsync(formElement,field, pkValues, oldName, newName); } - private static void RenamePhysicalFile(FormElement formElement, FormElementField field, string pkValues, string oldName, string newName) + private async Task RenamePhysicalFileAsync(FormElement formElement, FormElementField field, string pkValues, string oldName, string newName) { - var builder = new FormFilePathBuilder(formElement); - - var path = builder.GetFolderPath(field, DataHelper.GetPkValues(formElement, pkValues, ',')); - - var oldFilePath = Path.Combine(path, oldName); - var newFilePath = Path.Combine(path, newName); - - if (File.Exists(oldFilePath)) - File.Move(oldFilePath, newFilePath); - else - throw new KeyNotFoundException("File not found"); + var folderPath = FileStoragePath.GetFolderPath(formElement, field, DataHelper.GetPkValues(formElement, pkValues, ',')!); + await RenameFileAsync(folderPath, oldName, newName); } private async Task RenameEntityFileAsync(FormElement formElement, FormElementField field, string pkValues, string oldName, @@ -246,4 +231,3 @@ private async Task RenameEntityFileAsync(FormElement formElement, FormElementFie await entityRepository.SetValuesAsync(formElement, values); } } -#endif \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/Services/ElementMapService.cs b/src/MasterData.Core/DataManager/Services/ElementMapService.cs index 303397f19..6e71a9a64 100644 --- a/src/MasterData.Core/DataManager/Services/ElementMapService.cs +++ b/src/MasterData.Core/DataManager/Services/ElementMapService.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Collections.Generic; using System.Threading.Tasks; using JJMasterData.Commons.Data.Entity.Repository; diff --git a/src/MasterData.Core/DataManager/Services/FieldFormattingService.cs b/src/MasterData.Core/DataManager/Services/FieldFormattingService.cs index 873ed7cb5..9933803e4 100644 --- a/src/MasterData.Core/DataManager/Services/FieldFormattingService.cs +++ b/src/MasterData.Core/DataManager/Services/FieldFormattingService.cs @@ -35,10 +35,7 @@ public async ValueTask FormatGridValueAsync( case FormComponent.Percentage: stringValue = GetNumericValueAsString(field, value, $"N{field.NumberOfDecimalPlaces}"); if (!string.IsNullOrEmpty(stringValue)) - { - stringValue += "%"; - } - + stringValue += '%'; break; case FormComponent.Number: case FormComponent.Slider: @@ -51,12 +48,12 @@ public async ValueTask FormatGridValueAsync( when field.DataItem is { GridBehavior: not DataItemGridBehavior.Id }: var allowOnlyNumerics = field.DataType is FieldType.Int or FieldType.Float or FieldType.Decimal; stringValue = await lookupService.GetDescriptionAsync(field.DataItem.ElementMap!, formStateData, - value.ToString(), allowOnlyNumerics); + value.ToString(), allowOnlyNumerics) ?? string.Empty; break; case FormComponent.CheckBox: stringValue = StringManager.ParseBool(value) ? stringLocalizer["Yes"] : stringLocalizer["No"]; break; - case FormComponent.Search or FormComponent.ComboBox or FormComponent.RadioButtonGroup + case FormComponent.Search or FormComponent.ComboBox or FormComponent.RadioButtonGroup when field.DataItem is { GridBehavior: not DataItemGridBehavior.Id }: return await dataItemService.GetDescriptionAsync(fieldSelector.FormElement, field, formStateData, value); default: @@ -67,10 +64,10 @@ public async ValueTask FormatGridValueAsync( if (field.EncodeHtml) stringValue = HttpUtility.HtmlEncode(stringValue); - return stringValue ?? string.Empty; + return stringValue.Trim(); } - public static string FormatValue(FormElementField field, object value) + public static string FormatValue(FormElementField field, object? value) { var stringValue = value?.ToString(); if (string.IsNullOrEmpty(stringValue)) @@ -133,7 +130,7 @@ public static string FormatValue(FormElementField field, object value) return stringValue; } - private static string GetNumericValueAsString(FormElementField field, object value, [StringSyntax("NumericFormat")] string decimalFormat) + private static string GetNumericValueAsString(FormElementField field, object? value, [StringSyntax("NumericFormat")] string decimalFormat) { CultureInfo cultureInfo; if (field.Attributes.TryGetValue(FormElementField.CultureInfoAttribute, out var cultureInfoName) @@ -142,24 +139,24 @@ private static string GetNumericValueAsString(FormElementField field, object val else cultureInfo = CultureInfo.CurrentUICulture; - string stringValue = null; + string? stringValue = null; switch (field.DataType) { case FieldType.Float: { - if (value is double doubleValue || double.TryParse(value.ToString(), out doubleValue)) + if (value is double doubleValue || double.TryParse(value?.ToString(), out doubleValue)) stringValue = doubleValue.ToString(decimalFormat, cultureInfo); break; } case FieldType.Int: { - if (value is int intValue || int.TryParse(value.ToString(), out intValue)) + if (value is int intValue || int.TryParse(value?.ToString(), out intValue)) stringValue = intValue.ToString("0", cultureInfo); break; } case FieldType.Decimal: { - if (value is decimal decimalValue || decimal.TryParse(value.ToString(), out decimalValue)) + if (value is decimal decimalValue || decimal.TryParse(value?.ToString(), out decimalValue)) stringValue = decimalValue.ToString(decimalFormat, cultureInfo); break; } @@ -167,6 +164,6 @@ private static string GetNumericValueAsString(FormElementField field, object val throw new JJMasterDataException($"Invalid FieldType for numeric component [{field.Name}]"); } - return stringValue; + return stringValue ?? string.Empty; } } \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/Services/FieldValidationService.cs b/src/MasterData.Core/DataManager/Services/FieldValidationService.cs index 0e80d5eb5..00931bb18 100644 --- a/src/MasterData.Core/DataManager/Services/FieldValidationService.cs +++ b/src/MasterData.Core/DataManager/Services/FieldValidationService.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; +using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Data.Entity.Models; @@ -8,6 +10,7 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Models; +using JJMasterData.Core.DataManager.Services.Abstractions; using Microsoft.Extensions.Localization; @@ -15,11 +18,29 @@ namespace JJMasterData.Core.DataManager.Services; public class FieldValidationService( ExpressionsService expressionsService, + IEnumerable validationScriptExecutors, IStringLocalizer localizer) { + private Dictionary ValidationScriptExecutors { get; } = + validationScriptExecutors.ToDictionary(e => e.Language); + public Dictionary ValidateFields( FormElement formElement, - Dictionary formValues, + Dictionary formValues, + PageState pageState, + bool enableErrorLink) + { + var valueTask = ValidateFieldsAsync(formElement, formValues, pageState, enableErrorLink); + + if (valueTask.IsCompletedSuccessfully) + return valueTask.Result; + + return valueTask.AsTask().GetAwaiter().GetResult(); + } + + public async ValueTask> ValidateFieldsAsync( + FormElement formElement, + Dictionary formValues, PageState pageState, bool enableErrorLink) { @@ -49,20 +70,64 @@ public Dictionary ValidateFields( var error = ValidateField(field, field.Name, value, enableErrorLink); if (!string.IsNullOrEmpty(error)) - errors.Add(field.Name, error); + errors.Add(field.Name, error!); + } + + foreach (var error in await ValidateRulesAsync(formElement, formValues, enableErrorLink, pageState)) + { + errors[error.Key] = error.Value; + } + + return errors; + } + + public async Task> ValidateRulesAsync( + FormElement formElement, + Dictionary values, + bool enableErrorLink, + PageState pageState) + { + var errors = new Dictionary(); + + foreach (var rule in formElement.Rules.Where(r => r.ShouldRun(pageState))) + { + if (!ValidationScriptExecutors.TryGetValue(rule.Language, out var executor)) + { + errors[$"rule:{rule.Name}"] = + $"No script executor registered for language {rule.Language}."; + continue; + } + + var executionErrors = await executor.ExecuteAsync(formElement, rule, values); + foreach (var error in executionErrors) + { + if (formElement.Fields.TryGetField(error.Key, out var field)) + { + var fieldName = field.LabelOrName; + + if (enableErrorLink) + fieldName = GetFieldLinkHtml(field.Name, field.LabelOrName); + + errors[error.Key] = fieldName + " - " + localizer[error.Value]; + } + else + { + errors[error.Key] = localizer[error.Value]; + } + } } return errors; } - public string ValidateField(FormElementField field, string fieldId, object value, bool enableErrorLink = true) + public string? ValidateField(FormElementField field, string fieldId, object? value, bool enableErrorLink = true) { if (field == null) throw new ArgumentNullException(nameof(field)); var fieldName = enableErrorLink ? GetFieldLinkHtml(fieldId, field.LabelOrName) : localizer[field.LabelOrName]; - string error = null; + string? error = null; if (string.IsNullOrEmpty(value?.ToString())) { @@ -75,15 +140,15 @@ public string ValidateField(FormElementField field, string fieldId, object value { error = ValidateDataType(field, value, fieldName); - error ??= ValidateComponent(field, value, fieldName); + error ??= ValidateComponent(field, value!, fieldName); } return error; } - private string ValidateComponent(FormElementField field, object value, string fieldName) + private string? ValidateComponent(FormElementField field, object value, string fieldName) { - var valueString = value.ToString(); + var valueString = value.ToString()!; switch (field.Component) { case FormComponent.Email: @@ -143,32 +208,23 @@ private string ValidateComponent(FormElementField field, object value, string fi case FormComponent.Slider: if (field.Attributes.TryGetValue(FormElementField.MinValueAttribute, out var minValue)) { - if (double.Parse(value?.ToString()) < (double?)minValue) + if (double.Parse(value?.ToString()!) < (double?)minValue) return localizer["{0} field needs to be greater than {1}", fieldName, minValue]; } if (field.Attributes.TryGetValue(FormElementField.MaxValueAttribute, out var maxValue)) { - if (double.Parse(value?.ToString()) > (double?)maxValue) + if (double.Parse(value?.ToString()!) > (double?)maxValue) return localizer["{0} field needs to be less or equal than {1}", fieldName, maxValue]; } - break; - case FormComponent.Text: - case FormComponent.TextArea: - if (field.ValidateRequest && - value.ToString()?.IndexOf("= 0) - { - return localizer["{0} field contains invalid or not allowed character", fieldName]; - } - break; } return null; } - private string ValidateDataType(FormElementField field, object value, string fieldName) + private string? ValidateDataType(FormElementField field, object? value, string fieldName) { var dataType = field.DataType; switch (dataType) diff --git a/src/MasterData.Core/DataManager/Services/FieldValuesService.cs b/src/MasterData.Core/DataManager/Services/FieldValuesService.cs index dee66f00b..5c2b5fe5a 100644 --- a/src/MasterData.Core/DataManager/Services/FieldValuesService.cs +++ b/src/MasterData.Core/DataManager/Services/FieldValuesService.cs @@ -1,7 +1,5 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/DataManager/Services/FileValidationService.cs b/src/MasterData.Core/DataManager/Services/FileValidationService.cs new file mode 100644 index 000000000..dca72e435 --- /dev/null +++ b/src/MasterData.Core/DataManager/Services/FileValidationService.cs @@ -0,0 +1,102 @@ +using System.Collections.Frozen; +using System.IO; +using System.Linq; +using JJMasterData.Commons.Exceptions; +using JJMasterData.Commons.Util; +using Microsoft.Extensions.Localization; + +namespace JJMasterData.Core.DataManager.Services; + +public class FileValidationService(IStringLocalizer stringLocalizer) +{ + private static readonly FrozenSet BlockedExtensions = + [ + ".ade", + ".adp", + ".apk", + ".appx", + ".appxbundle", + ".bat", + ".cab", + ".chm", + ".cmd", + ".com", + ".cpl", + ".dll", + ".dmg", + ".ex", + ".ex_", + ".exe", + ".hta", + ".ins", + ".isp", + ".iso", + ".js", + ".jse", + ".lib", + ".lnk", + ".mde", + ".msc", + ".msi", + ".msix", + ".msixbundle", + ".msp", + ".mst", + ".nsh", + ".pif", + ".ps1", + ".scr", + ".sct", + ".sh", + ".shb", + ".sys", + ".vb", + ".vbe", + ".vbs", + ".vxd", + ".wsc", + ".wsf", + ".wsh", + ".jar", + ".cs", + ".cshtml", + ".bin" + ]; + + public void Validate(IFormFile file, string? allowedTypes = null) + { + var fileName = Path.GetFileName(file.FileName); + ValidateFileName(fileName); + ValidateAllowedExtensions(fileName, allowedTypes); + } + + public void ValidateFileName(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + throw new JJMasterDataException(stringLocalizer["Required file name"]); + + if (Path.GetFileName(fileName).Contains(',')) + throw new JJMasterDataException(stringLocalizer["The filename cannot contain comma."]); + } + + public void ValidateAllowedExtensions(string fileName, string? allowedTypes) + { + var extension = FileIO.GetFileNameExtension(fileName); + if (BlockedExtensions.Contains(extension)) + throw new JJMasterDataException(stringLocalizer["You cannot upload system files"]); + + if (string.IsNullOrWhiteSpace(allowedTypes) || allowedTypes.Equals("*")) + return; + + var allowedExtensions = allowedTypes + .Split(',') + .Select(type => type.Trim()) + .Where(type => type.Length > 0) + .Select(type => type.StartsWith('.') ? type : "." + type) + .ToHashSet(); + + if (allowedExtensions.Count > 0 && !allowedExtensions.Contains(extension)) + throw new JJMasterDataException( + stringLocalizer["File type is not allowed. Allowed extensions: {0}", allowedTypes]); + } +} diff --git a/src/MasterData.Core/DataManager/Services/FormService.cs b/src/MasterData.Core/DataManager/Services/FormService.cs index 951e0cacf..b74befd6d 100644 --- a/src/MasterData.Core/DataManager/Services/FormService.cs +++ b/src/MasterData.Core/DataManager/Services/FormService.cs @@ -1,3 +1,4 @@ + using System; using System.Collections.Generic; using System.Globalization; @@ -7,7 +8,6 @@ using JJMasterData.Commons.Exceptions; using JJMasterData.Commons.Tasks; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataManager.IO; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.Events.Args; using JJMasterData.Core.Logging; @@ -18,7 +18,6 @@ namespace JJMasterData.Core.DataManager.Services; public class FormService( IEntityRepository entityRepository, - FormFileService formFileService, FieldValidationService fieldValidationService, AuditLogService auditLogService, IStringLocalizer localizer, @@ -26,27 +25,27 @@ public class FormService( { #region Events - public event AsyncEventHandler OnBeforeDeleteAsync; - public event AsyncEventHandler OnAfterDeleteAsync; - public event AsyncEventHandler OnBeforeInsertAsync; - public event AsyncEventHandler OnAfterInsertAsync; - public event AsyncEventHandler OnBeforeUpdateAsync; - public event AsyncEventHandler OnAfterUpdateAsync; - public event AsyncEventHandler OnBeforeImportAsync; + public event AsyncEventHandler? OnBeforeDeleteAsync; + public event AsyncEventHandler? OnAfterDeleteAsync; + public event AsyncEventHandler? OnBeforeInsertAsync; + public event AsyncEventHandler? OnAfterInsertAsync; + public event AsyncEventHandler? OnBeforeUpdateAsync; + public event AsyncEventHandler? OnAfterUpdateAsync; + public event AsyncEventHandler? OnBeforeImportAsync; #endregion #region Methods public async Task>> GetAsync(FormElement formElement, - Dictionary filters) + Dictionary filters) { var errors = new Dictionary(); var formLetter = new FormLetter>(errors); try { - formLetter.Result = await entityRepository.GetFieldsAsync(formElement, filters); + formLetter.Result = (await entityRepository.GetFieldsAsync(formElement, filters!))!; } catch (Exception e) { @@ -63,12 +62,19 @@ public async Task>> GetAsync(FormElement f /// /// Values to be inserted. /// - public async Task UpdateAsync(FormElement formElement, Dictionary values, + public async Task UpdateAsync( + FormElement formElement, + Dictionary values, DataContext dataContext) { ApplyTextCaseTransform(formElement, values); var isForm = dataContext.Source is DataContextSource.Form; - var errors = fieldValidationService.ValidateFields(formElement, values, PageState.Update, isForm); + var errors = await fieldValidationService.ValidateFieldsAsync( + formElement, + values, + PageState.Update, + isForm); + var result = new FormLetter(errors); if (OnBeforeUpdateAsync != null) @@ -97,9 +103,6 @@ public async Task UpdateAsync(FormElement formElement, Dictionary 0) return result; - if (dataContext.Source == DataContextSource.Form) - formFileService.SaveFormMemoryFiles(formElement, values); - if (formElement.Options.EnableAuditLog) await auditLogService.LogAsync(formElement, dataContext, values, CommandOperation.Update); @@ -113,7 +116,7 @@ public async Task UpdateAsync(FormElement formElement, Dictionary InsertAsync(FormElement formElement, Dictionary values, + public async Task InsertAsync(FormElement formElement, Dictionary values, DataContext dataContext, bool validateFields = true) { ApplyTextCaseTransform(formElement, values); @@ -121,7 +124,11 @@ public async Task InsertAsync(FormElement formElement, Dictionary errors; if (validateFields) - errors = fieldValidationService.ValidateFields(formElement, values, PageState.Insert, isForm); + errors = await fieldValidationService.ValidateFieldsAsync( + formElement, + values, + PageState.Insert, + isForm); else errors = new Dictionary(); @@ -149,9 +156,6 @@ public async Task InsertAsync(FormElement formElement, Dictionary 0) return result; - if (dataContext.Source == DataContextSource.Form) - formFileService.SaveFormMemoryFiles(formElement, values); - if (formElement.Options.EnableAuditLog) await auditLogService.LogAsync(formElement, dataContext, values, CommandOperation.Insert); @@ -171,12 +175,17 @@ public async Task InsertAsync(FormElement formElement, Dictionary /// Values to be inserted. /// - public async Task> InsertOrReplaceAsync(FormElement formElement, - Dictionary values, DataContext dataContext) + public async Task> InsertOrReplaceAsync(FormElement formElement, Dictionary values, DataContext dataContext, bool validateFields = true) { ApplyTextCaseTransform(formElement, values); var isForm = dataContext.Source is DataContextSource.Form; - var errors = fieldValidationService.ValidateFields(formElement, values, PageState.Import, isForm); + + Dictionary errors; + if (validateFields) + errors = await fieldValidationService.ValidateFieldsAsync(formElement, values, PageState.Import, isForm); + else + errors = new(); + var letter = new FormLetter(errors); if (OnBeforeImportAsync != null) @@ -205,9 +214,6 @@ public async Task> InsertOrReplaceAsync(FormElement if (formElement.Options.EnableAuditLog) await auditLogService.LogAsync(formElement, dataContext, values, letter.Result); - if (dataContext.Source == DataContextSource.Form) - formFileService.SaveFormMemoryFiles(formElement, values); - switch (letter.Result) { case CommandOperation.Insert when OnAfterInsertAsync != null: @@ -247,12 +253,17 @@ public async Task> InsertOrReplaceAsync(FormElement public async Task DeleteAsync(FormElement formElement, Dictionary primaryKeys, DataContext dataContext) { - var errors = new Dictionary(); + var errors = await fieldValidationService.ValidateRulesAsync( + formElement, + primaryKeys!, + false, + PageState.Delete); + var result = new FormLetter(errors); if (OnBeforeDeleteAsync != null) { - var beforeActionArgs = new FormBeforeActionEventArgs(primaryKeys, errors); + var beforeActionArgs = new FormBeforeActionEventArgs(primaryKeys!, errors); await OnBeforeDeleteAsync(dataContext, beforeActionArgs); } @@ -273,15 +284,12 @@ public async Task DeleteAsync(FormElement formElement, Dictionary 0) return result; - if (dataContext.Source == DataContextSource.Form) - formFileService.DeleteFiles(formElement, primaryKeys); - if (formElement.Options.EnableAuditLog) - await auditLogService.LogAsync(formElement, dataContext, primaryKeys, CommandOperation.Delete); + await auditLogService.LogAsync(formElement, dataContext, primaryKeys!, CommandOperation.Delete); if (OnAfterDeleteAsync != null) { - var afterEventArgs = new FormAfterActionEventArgs(primaryKeys); + var afterEventArgs = new FormAfterActionEventArgs(primaryKeys!); await OnAfterDeleteAsync.Invoke(dataContext, afterEventArgs); result.UrlRedirect = afterEventArgs.UrlRedirect; } @@ -291,7 +299,7 @@ public async Task DeleteAsync(FormElement formElement, Dictionary values) + private static void ApplyTextCaseTransform(FormElement formElement, Dictionary values) { foreach (var field in formElement.Fields) { diff --git a/src/MasterData.Core/DataManager/Services/FormValuesService.cs b/src/MasterData.Core/DataManager/Services/FormValuesService.cs index a23609049..e3e7b03a8 100644 --- a/src/MasterData.Core/DataManager/Services/FormValuesService.cs +++ b/src/MasterData.Core/DataManager/Services/FormValuesService.cs @@ -1,5 +1,4 @@ -#nullable enable - + using System; using System.Collections.Generic; using System.Globalization; @@ -12,8 +11,6 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Exceptions; using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Logging; namespace JJMasterData.Core.DataManager.Services; @@ -23,7 +20,7 @@ public class FormValuesService( FieldValuesService fieldValuesService, IEncryptionService encryptionService, ILogger logger, - IHttpRequest httpRequest) + IHttpContextAccessor httpContextAccessor) { private Dictionary GetFormValues(FormElement formElement, string? fieldPrefix = null) @@ -36,13 +33,7 @@ public class FormValuesService( { var fieldName = (fieldPrefix ?? string.Empty) + field.Name; -#if NET48 - var value = field.ValidateRequest - ? httpRequest.Form[fieldName] - : httpRequest.Form.GetUnvalidated(fieldName); -#else - var value = httpRequest.Form[fieldName]; -#endif + var value = httpContextAccessor.HttpContext!.Request.GetFormValue(fieldName); HandleFieldValue(field, values, value); } @@ -62,7 +53,7 @@ internal static void HandleFieldValue(FormElementField field, Dictionary> GetDbValues(Element element) { - var encryptedPkValues = httpRequest.Form[ - $"data-panel-pk-values-{element.Name}"]; + var encryptedPkValues = httpContextAccessor.HttpContext!.Request.GetFormValue( + $"data-panel-pk-values-{element.Name}"); if (string.IsNullOrEmpty(encryptedPkValues)) { - var encryptedFkValues = httpRequest.Form[ - $"form-view-relation-values-{element.Name}"]; + var encryptedFkValues = httpContextAccessor.HttpContext!.Request.GetFormValue( + $"form-view-relation-values-{element.Name}"); if (!string.IsNullOrEmpty(encryptedFkValues)) { @@ -234,10 +219,10 @@ internal static void HandleFieldValue(FormElementField field, Dictionary(); - var pkValues = encryptionService.DecryptStringWithUrlUnescape(encryptedPkValues)!; + var pkValues = encryptionService.DecryptString(encryptedPkValues)!; var filters = DataHelper.GetPkValues(element, pkValues, '|'); var result = await entityRepository.GetFieldsAsync(element, filters); @@ -252,4 +237,4 @@ internal static void HandleFieldValue(FormElementField field, Dictionary stringLocalizer, - ILogger logger) + ILogger logger) { public async Task RenderTemplate( HtmlTemplateAction action, @@ -36,13 +32,15 @@ public async Task RenderTemplate( string renderedTemplate; try { - var command = ExpressionDataAccessCommandFactory.Create(action.SqlCommand, pkValues); + var parsedValues = pkValues.ToDictionary(x => x.Key, x => (object?)x.Value, StringComparer.InvariantCultureIgnoreCase); + var command = ExpressionDataAccessCommandFactory.Create(action.SqlCommand, parsedValues); var dataSource = await entityRepository.GetDataSetAsync(command, connectionId); - renderedTemplate = await RenderTemplate(action.HtmlTemplate, new Dictionary + var values = new Dictionary { { "DataSource", EnumerableHelper.ConvertDataSetToArray(dataSource) } - }); + }; + renderedTemplate = await htmlTemplateRenderer.RenderTemplate(action.HtmlTemplate, values); } catch (Exception ex) { @@ -70,9 +68,4 @@ public async Task RenderTemplate( return html; } - - public ValueTask RenderTemplate(string templateString, Dictionary values) - { - return htmlTemplateHelper.RenderTemplate(templateString, values); - } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Services/JavaScriptRuleScriptExecutor.cs b/src/MasterData.Core/DataManager/Services/JavaScriptRuleScriptExecutor.cs new file mode 100644 index 000000000..0dea71214 --- /dev/null +++ b/src/MasterData.Core/DataManager/Services/JavaScriptRuleScriptExecutor.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Threading.Tasks; +using Jint; +using Jint.Native; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataManager.Services.Abstractions; + +namespace JJMasterData.Core.DataManager.Services; + +public class JavaScriptRuleScriptExecutor : IRuleExecutor +{ + public RuleLanguage Language => RuleLanguage.JavaScript; + + public async Task> ExecuteAsync( + FormElement formElement, + FormElementRule rule, + Dictionary values) + { + var errors = new Dictionary(); + var index = 0; + IDictionary valuesObject = new ExpandoObject(); + foreach (var value in values) + { + valuesObject[value.Key] = value.Value; + } + + using var engine = new Engine(); + engine.SetValue("values", valuesObject); + engine.SetValue("formElement", formElement); + engine.SetValue("addError", new Action((first, second) => + { + var hasSecondArgument = !second?.IsUndefined() ?? false; + var key = hasSecondArgument ? first.ToString() : (++index).ToString(); + var message = hasSecondArgument ? second?.ToString() : first.ToString(); + + if (string.IsNullOrWhiteSpace(message)) + return; + + if (string.IsNullOrWhiteSpace(key)) + key = (++index).ToString(); + + if (!errors.ContainsKey(key)) + errors[key] = message ?? string.Empty; + })); + + await engine.ExecuteAsync(rule.Script); + + return errors; + } +} diff --git a/src/MasterData.Core/DataManager/Services/LookupService.cs b/src/MasterData.Core/DataManager/Services/LookupService.cs index 16ff2f101..632fd6b4c 100644 --- a/src/MasterData.Core/DataManager/Services/LookupService.cs +++ b/src/MasterData.Core/DataManager/Services/LookupService.cs @@ -1,18 +1,16 @@ -#nullable enable +#nullable disable warnings using System.Collections.Generic; using System.Threading.Tasks; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Components; namespace JJMasterData.Core.DataManager.Services; public class LookupService( - IFormValues formValues, + IHttpContextAccessor httpContextAccessor, ExpressionsService expressionsService, IEncryptionService encryptionService, ElementMapService elementMapService, @@ -25,7 +23,7 @@ public string GetFormViewUrl(DataElementMap elementMap, FormStateData? formState elementMap.EnableElementActions, elementMap.Filters); var encryptedLookupParameters = - encryptionService.EncryptStringWithUrlEscape( + encryptionService.EncryptString( lookupParameters.ToQueryString(expressionsService, formStateData)); return urlHelper.Action("Index", "Lookup", @@ -73,6 +71,6 @@ public string GetFormViewUrl(DataElementMap elementMap, FormStateData? formState public string? GetSelectedValue(string componentName) { - return formValues[componentName]; + return httpContextAccessor.HttpContext?.Request.GetFormValue(componentName); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/DataManager/Services/SqlRuleExecutor.cs b/src/MasterData.Core/DataManager/Services/SqlRuleExecutor.cs new file mode 100644 index 000000000..449fbc0c3 --- /dev/null +++ b/src/MasterData.Core/DataManager/Services/SqlRuleExecutor.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using JJMasterData.Commons.Data.Entity.Repository.Abstractions; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataManager.Expressions; +using JJMasterData.Core.DataManager.Services.Abstractions; + +namespace JJMasterData.Core.DataManager.Services; + +public class SqlRuleExecutor(IEntityRepository entityRepository) : IRuleExecutor +{ + public RuleLanguage Language => RuleLanguage.Sql; + + public async Task> ExecuteAsync( + FormElement formElement, + FormElementRule rule, + Dictionary values) + { + var command = ExpressionDataAccessCommandFactory.Create( + rule.Script, + values); + + var dataSet = await entityRepository.GetDataSetAsync(command, formElement.ConnectionId); + + var errors = new Dictionary(); + + if (dataSet.Tables.Count == 0) + return errors; + + foreach (DataTable dataTable in dataSet.Tables) + { + if (dataTable.Rows.Count == 0) + continue; + + var index = 0; + + foreach (DataRow row in dataTable.Rows) + { + index++; + + var (key, message) = GetError(row, index); + + if (!string.IsNullOrWhiteSpace(key) && + !string.IsNullOrWhiteSpace(message) && + !errors.ContainsKey(key)) + { + errors[key] = message; + } + } + } + + return errors; + } + + private static (string Key, string Message) GetError( + DataRow row, + int index) + { + var columns = row.Table.Columns; + + // Just one column? + if (columns.Count == 1) + { + var message = row[0]?.ToString() ?? string.Empty; + return (index.ToString(), message); + } + + var first = row[0]?.ToString(); + var second = row[1]?.ToString() ?? string.Empty; + + var key = string.IsNullOrWhiteSpace(first) + ? index.ToString() + : first!; + + return (key, second); + } +} diff --git a/src/MasterData.Core/DataManager/Services/UploadAreaService.cs b/src/MasterData.Core/DataManager/Services/UploadAreaService.cs deleted file mode 100644 index 3c27c15a0..000000000 --- a/src/MasterData.Core/DataManager/Services/UploadAreaService.cs +++ /dev/null @@ -1,168 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using JJMasterData.Commons.Exceptions; -using JJMasterData.Commons.Tasks; -using JJMasterData.Commons.Util; -using JJMasterData.Core.DataManager.IO; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.UI.Components; -using JJMasterData.Core.UI.Events.Args; -using Microsoft.Extensions.Localization; - -namespace JJMasterData.Core.DataManager.Services; - -public class UploadAreaService(IHttpContext currentContext, IStringLocalizer stringLocalizer) -{ - public event EventHandler? OnFileUploaded; - public event AsyncEventHandler? OnFileUploadedAsync; - - public async Task UploadFileAsync(FormFileContent formFile, string? allowedTypes = null) - { - UploadAreaResultDto dto = new(); - - try - { - var message = string.Empty; - - ValidateAllowedExtensions(formFile.FileName, allowedTypes); - - var args = new FormUploadFileEventArgs(formFile); - OnFileUploaded?.Invoke(this, args); - - if (OnFileUploadedAsync != null) - { - await OnFileUploadedAsync.Invoke(this, args); - } - - if (formFile.FileName.Contains(",")) - { - dto.ErrorMessage = stringLocalizer["The filename cannot contain comma."]; - return dto; - } - - var errorMessage = args.ErrorMessage; - if (args.SuccessMessage != null) - { - message = args.SuccessMessage; - } - - if (!string.IsNullOrEmpty(errorMessage)) - { - dto.ErrorMessage = errorMessage; - return dto; - } - - dto.SuccessMessage = message; - } - catch (JJMasterDataException ex) - { - dto.ErrorMessage = ex.Message; - } - - return dto; - } - - /// - /// Recovers the file after the POST - /// - private FormFileContent? GetFile(string fileName) - { - var fileData = currentContext.Request.Form.GetFile(fileName); - - if (fileData is null) - return null; - - using var stream = new MemoryStream(); - string filename = fileData.FileName; - -#if NETFRAMEWORK - fileData.InputStream.CopyTo(stream); -#else - fileData.CopyTo(stream); -#endif - - var content = new FormFileContent - { - FileName = filename, - Bytes = stream.ToArray(), - Length = stream.Length, - LastWriteTime = DateTime.Now - }; - - return content; - } - - public bool TryGetFile(string fileName, out FormFileContent? formFile) - { - formFile = GetFile(fileName); - - return formFile != null; - } - - private void ValidateAllowedExtensions(string filename, string? allowedTypes) - { - if (allowedTypes != null && !allowedTypes.Equals("*")) - return; - - var list = new List - { - ".ade", - ".adp", - ".apk", - ".appx", - ".appxbundle", - ".bat", - ".cab", - ".chm", - ".cmd", - ".com", - ".cpl", - ".dll", - ".dmg", - ".ex", - ".ex_", - ".exe", - ".hta", - ".ins", - ".isp", - ".iso", - ".js", - ".jse", - ".lib", - ".lnk", - ".mde", - ".msc", - ".msi", - ".msix", - ".msixbundle", - ".msp", - ".mst", - ".nsh", - ".pif", - ".ps1", - ".scr", - ".sct", - ".shb", - ".sys", - ".vb", - ".vbe", - ".vbs", - ".vxd", - ".wsc", - ".wsf", - ".wsh", - ".jar", - ".cs", - ".cshtml", - ".bin" - }; - - string ext = FileIO.GetFileNameExtension(filename); - if (list.Contains(ext)) - throw new JJMasterDataException(stringLocalizer["You cannot upload system files"]); - } -} \ No newline at end of file diff --git a/src/MasterData.Core/DataManager/Services/UrlRedirectService.cs b/src/MasterData.Core/DataManager/Services/UrlRedirectService.cs index 59836e52f..94bcb53ce 100644 --- a/src/MasterData.Core/DataManager/Services/UrlRedirectService.cs +++ b/src/MasterData.Core/DataManager/Services/UrlRedirectService.cs @@ -1,22 +1,29 @@ -using System.Collections.Generic; +#nullable disable warnings +using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using System.Web; using JJMasterData.Commons.Data.Entity.Repository.Abstractions; +using JJMasterData.Commons.Security; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Components; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Localization; namespace JJMasterData.Core.DataManager.Services; public class UrlRedirectService( - IHttpRequest httpRequest, + IHttpContextAccessor httpRequest, IEntityRepository entityRepository, + IStringLocalizer localizer, FormValuesService formValuesService, - ExpressionsService expressionsService) + ExpressionsService expressionsService, + HmacHelper hmacHelper) { public async Task GetUrlRedirectResult( JJDataPanel dataPanel, @@ -59,7 +66,7 @@ private JsonComponentResult GetJsonResult(Dictionary values, Url { var formStateData = new FormStateData(values, PageState.List); var parsedUrl = GetParsedUrl(action, formStateData); - var parsedTitle = expressionsService.ReplaceExpressionWithParsedValues(action.ModalTitle, formStateData); + var parsedTitle = GetParsedModalTitle(action, formStateData); var model = new UrlRedirectModel { @@ -78,10 +85,53 @@ public string GetParsedUrl(UrlRedirectAction action, FormStateData formStateData { var formStateDataCopy = formStateData.DeepCopy(); - formStateDataCopy.Values.Add("AppPath", httpRequest.ApplicationPath); + formStateDataCopy.Values.Add("AppPath", httpRequest.HttpContext?.Request.GetApplicationPath()); var decodedUrl = HttpUtility.UrlDecode(action.UrlRedirect); - return expressionsService.ReplaceExpressionWithParsedValues(decodedUrl, formStateDataCopy, action.EncryptParameters); + var parsedUrl = expressionsService.ReplaceExpressionWithParsedValues( + decodedUrl, + formStateDataCopy, + action.EncryptParameters) ?? string.Empty; + + return action.SignParametersWithHmac ? SignUrlParameters(parsedUrl) : parsedUrl; + } + + private string SignUrlParameters(string url) + { + var fragmentIndex = url.IndexOf('#'); + var fragment = fragmentIndex >= 0 ? url[fragmentIndex..] : string.Empty; + var urlWithoutFragment = fragmentIndex >= 0 ? url[..fragmentIndex] : url; + var questionMarkIndex = urlWithoutFragment.IndexOf('?'); + + if (questionMarkIndex < 0) + return url; + + var urlPath = urlWithoutFragment[..questionMarkIndex]; + var pathToSign = Uri.TryCreate(urlPath, UriKind.Absolute, out var absoluteUri) + ? absoluteUri.AbsolutePath + : urlPath; + var queryPairs = QueryHelpers.ParseQuery(urlWithoutFragment[questionMarkIndex..]) + .Where(pair => !pair.Key.Equals("signature", StringComparison.OrdinalIgnoreCase)) + .SelectMany(pair => pair.Value.Select(value => new KeyValuePair(pair.Key, value))) + .OrderBy(pair => pair.Key, StringComparer.OrdinalIgnoreCase) + .ThenBy(pair => pair.Value, StringComparer.Ordinal) + .ToList(); + + if (queryPairs.Count == 0) + return url; + + var content = QueryHelpers.AddQueryString(pathToSign, queryPairs); + var signature = hmacHelper.Generate(content); + var signedUrl = QueryHelpers.AddQueryString( + urlPath, + queryPairs.Append(new KeyValuePair("signature", signature))); + + return $"{signedUrl}{fragment}"; + } + + public string GetParsedModalTitle(UrlRedirectAction action, FormStateData formStateData) + { + return expressionsService.ReplaceExpressionWithParsedValues(localizer[action.ModalTitle], formStateData) ?? string.Empty; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/Events/Abstractions/EventHandlerResolverBase.cs b/src/MasterData.Core/Events/Abstractions/EventHandlerResolverBase.cs index 3d98da930..9b20e04dc 100644 --- a/src/MasterData.Core/Events/Abstractions/EventHandlerResolverBase.cs +++ b/src/MasterData.Core/Events/Abstractions/EventHandlerResolverBase.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using Microsoft.Extensions.DependencyInjection; namespace JJMasterData.Core.Events.Abstractions; diff --git a/src/MasterData.Core/Events/Abstractions/FormEventHandlerBase.cs b/src/MasterData.Core/Events/Abstractions/FormEventHandlerBase.cs index dab1745e8..d066ecd9f 100644 --- a/src/MasterData.Core/Events/Abstractions/FormEventHandlerBase.cs +++ b/src/MasterData.Core/Events/Abstractions/FormEventHandlerBase.cs @@ -1,18 +1,17 @@ using System.Threading.Tasks; using JJMasterData.Core.Events.Args; -using JJMasterData.Core.Tasks; namespace JJMasterData.Core.Events.Abstractions; public abstract class FormEventHandlerBase : IFormEventHandler { - public virtual ValueTask OnBeforeInsertAsync(object sender, FormBeforeActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnBeforeUpdateAsync(object sender, FormBeforeActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnBeforeDeleteAsync(object sender, FormBeforeActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnBeforeImportAsync(object sender, FormBeforeActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnAfterInsertAsync(object sender, FormAfterActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnAfterUpdateAsync(object sender, FormAfterActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnAfterDeleteAsync(object sender, FormAfterActionEventArgs args) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnFormElementLoadAsync(object sender, FormElementLoadEventArgs args) => ValueTaskHelper.CompletedTask; + public virtual ValueTask OnBeforeInsertAsync(object sender, FormBeforeActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnBeforeUpdateAsync(object sender, FormBeforeActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnBeforeDeleteAsync(object sender, FormBeforeActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnBeforeImportAsync(object sender, FormBeforeActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnAfterInsertAsync(object sender, FormAfterActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnAfterUpdateAsync(object sender, FormAfterActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnAfterDeleteAsync(object sender, FormAfterActionEventArgs args) => ValueTask.CompletedTask; + public virtual ValueTask OnFormElementLoadAsync(object sender, FormElementLoadEventArgs args) => ValueTask.CompletedTask; } diff --git a/src/MasterData.Core/Events/Abstractions/IFormEventHandlerResolver.cs b/src/MasterData.Core/Events/Abstractions/IFormEventHandlerResolver.cs index 177864dfc..6ab79d2e7 100644 --- a/src/MasterData.Core/Events/Abstractions/IFormEventHandlerResolver.cs +++ b/src/MasterData.Core/Events/Abstractions/IFormEventHandlerResolver.cs @@ -1,6 +1,4 @@ -#nullable enable - -namespace JJMasterData.Core.Events.Abstractions; +namespace JJMasterData.Core.Events.Abstractions; public interface IFormEventHandlerResolver { diff --git a/src/MasterData.Core/Events/Args/FormAfterActionEventArgs.cs b/src/MasterData.Core/Events/Args/FormAfterActionEventArgs.cs index 5f155cd01..217015090 100644 --- a/src/MasterData.Core/Events/Args/FormAfterActionEventArgs.cs +++ b/src/MasterData.Core/Events/Args/FormAfterActionEventArgs.cs @@ -3,13 +3,13 @@ namespace JJMasterData.Core.Events.Args; -public class FormAfterActionEventArgs(Dictionary values) : EventArgs +public class FormAfterActionEventArgs(Dictionary values) : EventArgs { - public Dictionary Values { get; set; } = values; + public Dictionary Values { get; set; } = values; - public string UrlRedirect { get; set; } + public string? UrlRedirect { get; set; } - public FormAfterActionEventArgs() : this(new Dictionary()) + public FormAfterActionEventArgs() : this(new Dictionary()) { } } diff --git a/src/MasterData.Core/Events/Args/FormBeforeActionEventArgs.cs b/src/MasterData.Core/Events/Args/FormBeforeActionEventArgs.cs index 01c5ea925..8eda7ba52 100644 --- a/src/MasterData.Core/Events/Args/FormBeforeActionEventArgs.cs +++ b/src/MasterData.Core/Events/Args/FormBeforeActionEventArgs.cs @@ -3,10 +3,10 @@ namespace JJMasterData.Core.Events.Args; -public class FormBeforeActionEventArgs(Dictionary values, Dictionary errors) +public class FormBeforeActionEventArgs(Dictionary values, Dictionary errors) : EventArgs { - public Dictionary Values { get; set; } = values; + public Dictionary Values { get; set; } = values; public Dictionary Errors { get; set; } = errors; } diff --git a/src/MasterData.Core/Events/Args/SearchBoxItemEventArgs.cs b/src/MasterData.Core/Events/Args/SearchBoxItemEventArgs.cs index c748fb6d2..eda101d96 100644 --- a/src/MasterData.Core/Events/Args/SearchBoxItemEventArgs.cs +++ b/src/MasterData.Core/Events/Args/SearchBoxItemEventArgs.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; namespace JJMasterData.Core.Events.Args; diff --git a/src/MasterData.Core/Events/Args/SearchBoxQueryEventArgs.cs b/src/MasterData.Core/Events/Args/SearchBoxQueryEventArgs.cs index 32df3ce56..c30ffcad5 100644 --- a/src/MasterData.Core/Events/Args/SearchBoxQueryEventArgs.cs +++ b/src/MasterData.Core/Events/Args/SearchBoxQueryEventArgs.cs @@ -1,12 +1,13 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using JJMasterData.Core.DataDictionary.Models; namespace JJMasterData.Core.Events.Args; -public class SearchBoxQueryEventArgs(string textSearch) : EventArgs +public class SearchBoxQueryEventArgs(string? searchText) : EventArgs { - public string TextSearch { get; set; } = textSearch; + public string? SearchText { get; set; } = searchText; public IEnumerable Values { get; set; } } diff --git a/src/MasterData.Core/Events/FormEventHandlerResolver.cs b/src/MasterData.Core/Events/FormEventHandlerResolver.cs index ea326e031..baab2a42b 100644 --- a/src/MasterData.Core/Events/FormEventHandlerResolver.cs +++ b/src/MasterData.Core/Events/FormEventHandlerResolver.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using JJMasterData.Core.Events.Abstractions; diff --git a/src/MasterData.Core/Extensions/ClaimsPrincipalExtensions.cs b/src/MasterData.Core/Extensions/ClaimsPrincipalExtensions.cs index fbf1be771..a29d347e8 100644 --- a/src/MasterData.Core/Extensions/ClaimsPrincipalExtensions.cs +++ b/src/MasterData.Core/Extensions/ClaimsPrincipalExtensions.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Security.Claims; +using System.Security.Claims; namespace JJMasterData.Core.Extensions; diff --git a/src/MasterData.Core/Extensions/CookieExtensions.cs b/src/MasterData.Core/Extensions/CookieExtensions.cs new file mode 100644 index 000000000..cdca0de96 --- /dev/null +++ b/src/MasterData.Core/Extensions/CookieExtensions.cs @@ -0,0 +1,151 @@ +#nullable enable annotations +#nullable disable warnings +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Security.Cryptography; +using System.Text.Json; +using JJMasterData.Commons.Serialization; +using JJMasterData.Core.UI.Components; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.DependencyInjection; + +namespace JJMasterData.Core.Extensions; + +public static class CookieExtensions +{ + private const string Prefix = ".JJMasterData."; + private const string GridCookiePrefix = "Grid."; + private const string FilterCookieSuffix = ".Filter"; + private const string OrderCookieSuffix = ".Order"; + private const string PageCookieSuffix = ".Page"; + private const string SettingsCookieSuffix = ".Settings"; + + extension(HttpContext httpContext) + { + public Dictionary? GetGridFilterCookie(string gridName) + { + var cookieValue = httpContext.GetDecodedCookieValue(GetGridCookieKey(gridName, FilterCookieSuffix)); + if (string.IsNullOrEmpty(cookieValue)) + return null; + + try + { + var unprotectedValue = httpContext.GetGridFilterCookieProtector().Unprotect(cookieValue); + var filter = JsonSerializer.Deserialize>(unprotectedValue, MasterDataJsonSerializerOptions.Default); + + if (filter == null || filter.Count == 0) + return null; + + return filter; + } + catch (CryptographicException) + { + return null; + } + catch (JsonException) + { + return null; + } + } + + public void SetGridFilterCookie(string gridName, Dictionary filterValues) + { + var serializedValue = filterValues is { Count: > 0 } + ? JsonSerializer.Serialize(filterValues, MasterDataJsonSerializerOptions.Default) + : null; + + serializedValue = serializedValue == null + ? null + : httpContext.GetGridFilterCookieProtector().Protect(serializedValue); + + httpContext.SetCookieValue(GetGridCookieKey(gridName, FilterCookieSuffix), serializedValue); + } + + public string GetGridOrderCookie(string gridName) + { + return httpContext.GetDecodedCookieValue(GetGridCookieKey(gridName, OrderCookieSuffix)); + } + + public void SetGridOrderCookie(string gridName, string orderBy) + { + httpContext.SetCookieValue(GetGridCookieKey(gridName, OrderCookieSuffix), string.IsNullOrEmpty(orderBy) ? null : orderBy); + } + + public int? GetGridCurrentPageCookie(string gridName) + { + var cookieValue = httpContext.GetDecodedCookieValue(GetGridCookieKey(gridName, PageCookieSuffix)); + if (string.IsNullOrEmpty(cookieValue)) + return null; + + return int.TryParse(cookieValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out var page) + ? page + : null; + } + + public void SetGridCurrentPageCookie(string gridName, int page) + { + httpContext.SetCookieValue(GetGridCookieKey(gridName, PageCookieSuffix), page.ToString(CultureInfo.InvariantCulture)); + } + + public GridSettings GetGridSettingsCookie(string gridName) + { + var cookieValue = httpContext.GetDecodedCookieValue(GetGridCookieKey(gridName, SettingsCookieSuffix)); + if (string.IsNullOrEmpty(cookieValue)) + return null; + + return JsonSerializer.Deserialize(cookieValue, MasterDataJsonSerializerOptions.Default); + } + + public void SetGridSettingsCookie(string gridName, GridSettings settings) + { + var serializedValue = settings == null + ? null + : JsonSerializer.Serialize(settings, MasterDataJsonSerializerOptions.Default); + + httpContext.SetCookieValue(GetGridCookieKey(gridName, SettingsCookieSuffix), serializedValue); + } + + private void SetCookieValue(string key, string value) + { + if (string.IsNullOrEmpty(value)) + { + httpContext.Response.Cookies.Delete(key, httpContext.CreateCookieOptions()); + return; + } + + httpContext.Response.Cookies.Append(key, Uri.EscapeDataString(value), httpContext.CreateCookieOptions()); + } + + private CookieOptions CreateCookieOptions() + { + return new CookieOptions + { + HttpOnly = true, + IsEssential = true, + Path = httpContext.Request.PathBase.HasValue + ? httpContext.Request.PathBase.Value + : "/", + SameSite = SameSiteMode.Lax, + Secure = httpContext.Request.IsHttps + }; + } + + private string GetDecodedCookieValue(string key) + { + var value = httpContext.Request.Cookies[key]; + return string.IsNullOrEmpty(value) ? value : Uri.UnescapeDataString(value); + } + + private IDataProtector GetGridFilterCookieProtector() + { + var provider = httpContext.RequestServices.GetRequiredService(); + return provider.CreateProtector("JJMasterData GridView filter cookie."); + } + } + + private static string GetGridCookieKey(string gridName, string suffix = null) + { + return $"{Prefix}{GridCookiePrefix}{gridName.ToLowerInvariant()}{suffix}"; + } +} diff --git a/src/MasterData.Core/Extensions/EncryptionServiceExtensions.cs b/src/MasterData.Core/Extensions/EncryptionServiceExtensions.cs index 01d32b2ba..dd3619708 100644 --- a/src/MasterData.Core/Extensions/EncryptionServiceExtensions.cs +++ b/src/MasterData.Core/Extensions/EncryptionServiceExtensions.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using System.Collections.Generic; using System.Text.Json; @@ -12,34 +13,14 @@ public static class EncryptionServiceExtensions { extension(IEncryptionService service) { - /// - /// Encrypts the string with URL escape to prevent errors in parsing, algorithms like AES generate characters like '/' - /// - /// - /// - public string EncryptStringWithUrlEscape(string plainText) - { - return Uri.EscapeDataString(service.EncryptString(plainText)); - } - - /// - /// Decrypts the string with URL unescape to prevent errors in parsing, algorithms like AES generate characters like '/' - /// - /// - /// - public string DecryptStringWithUrlUnescape(string cipherText) - { - return service.DecryptString(Uri.UnescapeDataString(cipherText)); - } - public string EncryptObject(T @object) { - return service.EncryptStringWithUrlEscape(JsonSerializer.Serialize(@object, MasterDataJsonSerializerOptions.Default)); + return service.EncryptString(JsonSerializer.Serialize(@object, MasterDataJsonSerializerOptions.Default)); } public T DecryptObject(string encryptedObject) { - return JsonSerializer.Deserialize(service.DecryptStringWithUrlUnescape(encryptedObject)!, MasterDataJsonSerializerOptions.Default); + return JsonSerializer.Deserialize(service.DecryptString(encryptedObject), MasterDataJsonSerializerOptions.Default); } public Dictionary DecryptDictionary(string encryptedDictionary) diff --git a/src/MasterData.Core/Extensions/FileStoragePathExtensions.cs b/src/MasterData.Core/Extensions/FileStoragePathExtensions.cs new file mode 100644 index 000000000..fdbf8e59a --- /dev/null +++ b/src/MasterData.Core/Extensions/FileStoragePathExtensions.cs @@ -0,0 +1,33 @@ +#nullable disable warnings +using System; +using System.Collections.Generic; +using JJMasterData.Commons.Storage; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataManager; + +namespace JJMasterData.Core.Extensions; + +public static class FileStoragePathExtensions +{ + extension(FileStoragePath) + { + public static string GetFolderPath(FormElement formElement, FormElementField field, Dictionary values) + { + if (field.DataFile == null) + throw new ArgumentException(@$"{nameof(FormElementField.DataFile)} not defined.", field.Name); + + if (string.IsNullOrEmpty(field.DataFile.FolderPath)) + throw new ArgumentException(@$"{nameof(FormElementField.DataFile.FolderPath)} cannot be empty.", + field.Name); + + var pkValues = DataHelper.ParsePkValues(formElement, values, '_'); + + return FileStoragePath.CombineKey(field.DataFile.FolderPath, pkValues); + } + + private static string CombineKey(string rootKey, string childKey) + { + return string.IsNullOrEmpty(childKey) ? rootKey : $"{rootKey.TrimEnd('/', '\\')}/{childKey}"; + } + } +} diff --git a/src/MasterData.Core/Extensions/HtmlBuilderExtensions.cs b/src/MasterData.Core/Extensions/HtmlBuilderExtensions.cs index 5863de2f9..72f87a4c7 100644 --- a/src/MasterData.Core/Extensions/HtmlBuilderExtensions.cs +++ b/src/MasterData.Core/Extensions/HtmlBuilderExtensions.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; -using Microsoft.AspNetCore.Html; namespace JJMasterData.Core.Extensions; diff --git a/src/MasterData.Core/Extensions/HttpContextExtensions.cs b/src/MasterData.Core/Extensions/HttpContextExtensions.cs index ee350da02..f6f01f505 100644 --- a/src/MasterData.Core/Extensions/HttpContextExtensions.cs +++ b/src/MasterData.Core/Extensions/HttpContextExtensions.cs @@ -1,17 +1,54 @@ -using JJMasterData.Core.Http.Abstractions; +using System; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.Options; namespace JJMasterData.Core.Extensions; public static class HttpContextExtensions { - public static bool TryGetValue(this IFormValues formValues, string key, out string value) + extension(HttpRequest request) { - value = formValues[key]; - return !string.IsNullOrEmpty(value); - } - public static bool TryGetValue(this IQueryString queryString,string key, out string value) + public string GetApplicationPath() + { + return request.PathBase.ToString(); + } + + /// + /// Recover the value of a key from the query string or form data. Query string takes precedence over form data. + /// + public string? GetValue(string key) + { + if (request.Query.ContainsKey(key)) + return request.Query[key]; + + if (request.HasFormContentType) + return request.Form[key]; + + return null; + } + + public string? GetFormValue(string key) + { + return request.HasFormContentType ? request.Form[key] : (string?)null; + } + + public string GetApplicationUri() + { + return new Uri($"{request.Scheme}://{request.Host}{request.PathBase}").ToString(); + } + + public string GetAbsoluteUri() + { + return request.GetDisplayUrl(); + } + } + + extension(IOptions options) { - value = queryString[key]; - return !string.IsNullOrWhiteSpace(value); - } -} \ No newline at end of file + public long GetMaxRequestBodySize() + { + return options.Value.MultipartBodyLengthLimit; + } + } +} diff --git a/src/MasterData.Core/Extensions/SessionExtensions.cs b/src/MasterData.Core/Extensions/SessionExtensions.cs deleted file mode 100644 index cfd23126e..000000000 --- a/src/MasterData.Core/Extensions/SessionExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -#if NET - -using System.Text.Json; -using JJMasterData.Commons.Serialization; -using Microsoft.AspNetCore.Http; - -namespace JJMasterData.Core.Extensions; - -public static class SessionExtensions -{ - public static void SetObject(this ISession session, string key, object value) - { - if (value is null) - { - session.Remove(key); - } - else - { - session.SetString(key, JsonSerializer.Serialize(value, MasterDataJsonSerializerOptions.Default)); - } - } - - public static T GetObject(this ISession session, string key) - { - var value = session.GetString(key); - return value == null ? default : JsonSerializer.Deserialize(value, MasterDataJsonSerializerOptions.Default); - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Extensions/StringExtensions.cs b/src/MasterData.Core/Extensions/StringExtensions.cs deleted file mode 100644 index aa51b0285..000000000 --- a/src/MasterData.Core/Extensions/StringExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -#if !NET -using System; - -namespace JJMasterData.Core.Extensions; - -public static class StringExtensions -{ - public static bool Contains(this string str, string substring, StringComparison comparisonType) - { - return str.IndexOf(substring, comparisonType) >= 0; - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Html/Templates/HtmlTemplateContext.cs b/src/MasterData.Core/Html/Templates/HtmlTemplateContext.cs new file mode 100644 index 000000000..aaeb35594 --- /dev/null +++ b/src/MasterData.Core/Html/Templates/HtmlTemplateContext.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using Fluid; + +namespace JJMasterData.Core.Html.Templates; + +internal sealed class HtmlTemplateContext : TemplateContext +{ + public HtmlTemplateContext(IServiceProvider serviceProvider, Dictionary values) : base(values, HtmlTemplateOptions.Value, allowModelMembers: true) + { + AmbientValues[HtmlTemplateOptions.ServiceProviderKey] = serviceProvider; + } +} \ No newline at end of file diff --git a/src/MasterData.Core/Html/Templates/HtmlTemplateFunctions.cs b/src/MasterData.Core/Html/Templates/HtmlTemplateFunctions.cs deleted file mode 100644 index b6afb08d6..000000000 --- a/src/MasterData.Core/Html/Templates/HtmlTemplateFunctions.cs +++ /dev/null @@ -1,199 +0,0 @@ -#nullable enable - -using System; -using System.Globalization; -using System.Linq; -using System.Web; -using Fluid.Values; -using JJMasterData.Commons.Util; -using JJMasterData.Core.Http.Abstractions; -using JJConsulting.Html; -using JJConsulting.Html.Extensions; -using Microsoft.Extensions.Localization; - -namespace JJMasterData.Core.Html.Templates; - -public class HtmlTemplateFunctions( - IStringLocalizer stringLocalizer, - RelativeDateFormatter dateFormatter, - IHttpContext httpContext) -{ - public FunctionValue GetDateAsText() - { - var formatter = new FunctionValue((args, _) => - { - var dateArg = args.At(0).ToStringValue(); - - if (DateTime.TryParse(dateArg, out var date)) - { - var phrase = dateFormatter.ToRelativeString(date); - - return StringValue.Create(phrase); - } - - return StringValue.Empty; - }); - return formatter; - } - - public FunctionValue GetLocalizeFunction() - { - var localize = new FunctionValue((args, _) => - { - var firstArg = args.At(0).ToStringValue(); - var localizerArgs = args.Values.Skip(1).Select(v => v.ToStringValue()).ToArray(); - - var localizedString = stringLocalizer[firstArg, localizerArgs.ToArray()]; - - return StringValue.Create(localizedString); - }); - return localize; - } - - public FunctionValue GetUrlPathFunction() - { - var urlAction = new FunctionValue((_, _) => StringValue.Create(httpContext.Request.ApplicationPath)); - - return urlAction; - } - - public FunctionValue GetAppUrlFunction() - { - var urlAction = new FunctionValue((_, _) => StringValue.Create(httpContext.Request.ApplicationUri)); - - return urlAction; - } - - public static readonly FunctionValue FormatDate = new((args, _) => - { - var obj = args.At(0).ToStringValue(); - var format = args.At(1).ToStringValue(); - - return StringValue.Create(DateTime.TryParse(obj, out var dt) ? dt.ToString(format) : obj); - }); - - public static readonly FunctionValue Trim = new((args, _) => - { - var str = args.At(0).ToStringValue(); - - return StringValue.Create(str.Trim()); - }); - - public static readonly FunctionValue TrimStart = new((args, _) => - { - var str = args.At(0).ToStringValue(); - - return StringValue.Create(str.TrimStart()); - }); - - public static readonly FunctionValue TrimEnd = new((args, _) => - { - var str = args.At(0).ToStringValue(); - - return StringValue.Create(str.TrimEnd()); - }); - - public static readonly FunctionValue IsNullOrEmpty = new((args, _) => - { - var str = args.At(0).ToStringValue(); - return BooleanValue.Create(string.IsNullOrEmpty(str)); - }); - - public static readonly FunctionValue IsNullOrWhiteSpace = new((args, _) => - { - var str = args.At(0).ToStringValue(); - return BooleanValue.Create(string.IsNullOrWhiteSpace(str)); - }); - - public static readonly FunctionValue Capitalize = new((args, _) => - { - var str = args.At(0).ToStringValue(); - return StringValue.Create(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str?.ToLower() ?? string.Empty)); - }); - - public static readonly FunctionValue Substring = new((args, _) => - { - if (args.Count < 2) - { - return new StringValue("Error: Not enough arguments"); - } - - var str = args.At(0).ToObjectValue().ToString()!; - if (!int.TryParse(args.At(1).ToStringValue(), out var startIndex)) - { - return new StringValue("Error: Invalid start index"); - } - - int length = 0; - - if (args.Count > 2 && !int.TryParse(args.At(2).ToStringValue(), out length)) - { - return new StringValue("Error: Invalid length"); - } - - var substring = args.Count > 2 - ? str.Substring(startIndex, length) - : str[startIndex..]; - - return new StringValue(substring); - }); - - public static readonly FunctionValue Table = new((args, _) => - { - var arrayValue = args.At(0).ToObjectValue() as object[]; - - if (arrayValue == null || arrayValue.Length == 0) - return StringValue.Empty; - - var dataSource = arrayValue - .Select(v => (IFluidIndexable)v) - .ToList(); - - var headers = dataSource[0].Keys; - - var builder = new HtmlBuilder(HtmlTag.Div) - .WithCssClass("table-responsive"); - - builder.Append(HtmlTag.Table, table => - { - table.WithCssClass("table table-striped table-hover"); - - table.Append(HtmlTag.Thead, thead => - { - thead.Append(HtmlTag.Tr, tr => - { - foreach (var header in headers) - { - tr.Append(HtmlTag.Th, th => th.AppendText(header)); - } - }); - }); - - table.Append(HtmlTag.Tbody, tbody => - { - foreach (var row in dataSource) - { - tbody.Append(HtmlTag.Tr, tr => - { - foreach (var header in headers) - { - tr.Append(HtmlTag.Td, td => - { - if (row.TryGetValue(header, out var value)) - { - td.AppendText(value?.ToStringValue()); - } - else - { - td.AppendText(""); - } - }); - } - }); - } - }); - }); - - return new StringValue(builder.ToString(), encode: false); - }); -} \ No newline at end of file diff --git a/src/MasterData.Core/Html/Templates/HtmlTemplateHelper.cs b/src/MasterData.Core/Html/Templates/HtmlTemplateHelper.cs deleted file mode 100644 index 6b2462d21..000000000 --- a/src/MasterData.Core/Html/Templates/HtmlTemplateHelper.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Encodings.Web; -using System.Threading.Tasks; -using Fluid; -using JetBrains.Annotations; -using static JJMasterData.Core.Html.Templates.HtmlTemplateFunctions; - -namespace JJMasterData.Core.Html.Templates; - -[PublicAPI] -public class HtmlTemplateHelper( - FluidParser fluidParser, - HtmlTemplateFunctions functions) -{ - public IFluidTemplate ParseTemplate(string template) - { - return fluidParser.Parse(template); - } - - public ValueTask RenderTemplate(string templateString, Dictionary values) - { - if (!fluidParser.TryParse(templateString, out var template, out var error)) - return new(error); - - var context = new TemplateContext(values, allowModelMembers:true, StringComparer.InvariantCultureIgnoreCase); - - SetDefaultValues(context); - - return template.RenderAsync(context, HtmlEncoder.Default); - } - - public ValueTask RenderTemplate( - string templateString, - TemplateContext context) - { - if (!fluidParser.TryParse(templateString, out var template, out var error)) - return new(error); - - SetDefaultValues(context); - - return template.RenderAsync(context, HtmlEncoder.Default); - } - - public ValueTask RenderTemplate(IFluidTemplate template, TemplateContext context) - { - SetDefaultValues(context); - - return template.RenderAsync(context, HtmlEncoder.Default); - } - - private void SetDefaultValues(TemplateContext context) - { - context.SetValue("isNullOrWhiteSpace", IsNullOrWhiteSpace); - context.SetValue("isNullOrEmpty", IsNullOrEmpty); - context.SetValue("substring", Substring); - context.SetValue("capitalize", Capitalize); - context.SetValue("formatDate", FormatDate); - context.SetValue("trim", Trim); - context.SetValue("trimStart", TrimStart); - context.SetValue("trimEnd", TrimEnd); - context.SetValue("table", Table); - context.SetValue("dateAsText", functions.GetDateAsText()); - context.SetValue("urlPath", functions.GetUrlPathFunction()); - context.SetValue("appUrl", functions.GetAppUrlFunction()); - context.SetValue("localize", functions.GetLocalizeFunction()); - } -} \ No newline at end of file diff --git a/src/MasterData.Core/Html/Templates/HtmlTemplateOptions.cs b/src/MasterData.Core/Html/Templates/HtmlTemplateOptions.cs new file mode 100644 index 000000000..9f2d906c3 --- /dev/null +++ b/src/MasterData.Core/Html/Templates/HtmlTemplateOptions.cs @@ -0,0 +1,285 @@ +#nullable disable warnings +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using Fluid; +using Fluid.Values; +using JJConsulting.Html; +using JJConsulting.Html.Extensions; +using JJMasterData.Commons.Util; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.UI.Components; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; + +namespace JJMasterData.Core.Html.Templates; + +public static class HtmlTemplateOptions +{ + internal const string ServiceProviderKey = "ServiceProvider"; + internal const string FormElementKey = "FormElement"; + internal const string FormElementFieldKey = "_FormElementField"; + internal const string FormValuesKey = "FormValues"; + + public static readonly TemplateOptions Value; + + static HtmlTemplateOptions() + { + var options = new TemplateOptions(); + options.Scope.SetValue("isNullOrWhiteSpace", IsNullOrWhiteSpace); + options.Scope.SetValue("isNullOrEmpty", IsNullOrEmpty); + options.Scope.SetValue("substring", Substring); + options.Scope.SetValue("capitalize", Capitalize); + options.Scope.SetValue("formatDate", FormatDate); + options.Scope.SetValue("trim", Trim); + options.Scope.SetValue("trimStart", TrimStart); + options.Scope.SetValue("trimEnd", TrimEnd); + options.Scope.SetValue("table", Table); + options.Scope.SetValue("dateAsText", DateAsText); + options.Scope.SetValue("urlPath", UrlPath); + options.Scope.SetValue("appUrl", AppUrl); + options.Scope.SetValue("localize", Localize); + options.Scope.SetValue("getFileUrl", GetFileUrl); + options.Scope.SetValue("isImage", IsImage); + + options.ModelNamesComparer = StringComparer.OrdinalIgnoreCase; + + Value = options; + } + + private static readonly FunctionValue DateAsText = new((args, context) => + { + var dateFormatter = GetRequiredService(context); + var dateArg = args.At(0).ToStringValue(); + + if (DateTime.TryParse(dateArg, out var date)) + { + var phrase = dateFormatter.ToRelativeString(date); + return StringValue.Create(phrase); + } + + return StringValue.Empty; + }); + + private static readonly FunctionValue Localize = new((args, context) => + { + var stringLocalizer = GetRequiredService>(context); + var firstArg = args.At(0).ToStringValue(); + var localizerArgs = args.Values.Skip(1).Select(v => v.ToStringValue()).ToArray(); + var localizedString = stringLocalizer[firstArg, localizerArgs]; + + return StringValue.Create(localizedString); + }); + + private static readonly FunctionValue UrlPath = new((_, context) => + { + var httpContextAccessor = GetRequiredService(context); + return StringValue.Create(httpContextAccessor.HttpContext?.Request.GetApplicationPath()); + }); + + private static readonly FunctionValue AppUrl = new((_, context) => + { + var httpContextAccessor = GetRequiredService(context); + return StringValue.Create(httpContextAccessor.HttpContext?.Request.GetApplicationUri()); + }); + + private static readonly FunctionValue GetFileUrl = new((args, context) => + { + if (!TryGetAmbientValue(context, FormElementKey, out var formElement) || + !TryGetAmbientValue(context, FormElementFieldKey, out var field) || + !TryGetAmbientValue>(context, FormValuesKey, out var values) || + field.DataFile is null) + { + return StringValue.Empty; + } + + var fileName = args.At(0).ToStringValue(); + if (string.IsNullOrWhiteSpace(fileName)) + return StringValue.Empty; + + if(values.Count == 0) + return StringValue.Empty; + + var fileDownloaderFactory = GetRequiredService(context); + var url = fileDownloaderFactory + .Create(formElement, field, values, fileName) + .GetDownloadUrl(); + + return StringValue.Create(url); + }); + + private static readonly FunctionValue FormatDate = new((args, _) => + { + var obj = args.At(0).ToStringValue(); + var format = args.At(1).ToStringValue(); + + return StringValue.Create(DateTime.TryParse(obj, out var dt) ? dt.ToString(format) : obj); + }); + + private static readonly FunctionValue Trim = new((args, _) => + { + var str = args.At(0).ToStringValue(); + + return StringValue.Create(str.Trim()); + }); + + private static readonly FunctionValue TrimStart = new((args, _) => + { + var str = args.At(0).ToStringValue(); + + return StringValue.Create(str.TrimStart()); + }); + + private static readonly FunctionValue TrimEnd = new((args, _) => + { + var str = args.At(0).ToStringValue(); + + return StringValue.Create(str.TrimEnd()); + }); + + private static readonly FunctionValue IsNullOrEmpty = new((args, _) => + { + var str = args.At(0).ToStringValue(); + return BooleanValue.Create(string.IsNullOrEmpty(str)); + }); + + private static readonly FunctionValue IsNullOrWhiteSpace = new((args, _) => + { + var str = args.At(0).ToStringValue(); + return BooleanValue.Create(string.IsNullOrWhiteSpace(str)); + }); + + private static readonly FunctionValue IsImage = new((args, _) => + { + var fileName = args.At(0).ToStringValue(); + return BooleanValue.Create(IsImageFile(fileName)); + }); + + private static readonly FunctionValue Capitalize = new((args, _) => + { + var str = args.At(0).ToStringValue(); + return StringValue.Create(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str?.ToLower() ?? string.Empty)); + }); + + private static readonly FunctionValue Substring = new((args, _) => + { + if (args.Count < 2) + { + return new StringValue("Error: Not enough arguments"); + } + + var str = args.At(0).ToObjectValue().ToString()!; + if (!int.TryParse(args.At(1).ToStringValue(), out var startIndex)) + { + return new StringValue("Error: Invalid start index"); + } + + int length = 0; + + if (args.Count > 2 && !int.TryParse(args.At(2).ToStringValue(), out length)) + { + return new StringValue("Error: Invalid length"); + } + + var substring = args.Count > 2 + ? str.Substring(startIndex, length) + : str[startIndex..]; + + return new StringValue(substring); + }); + + private static readonly FunctionValue Table = new((args, _) => + { + var arrayValue = args.At(0).ToObjectValue() as object[]; + + if (arrayValue == null || arrayValue.Length == 0) + return StringValue.Empty; + + var dataSource = arrayValue + .Select(v => (IFluidIndexable)v) + .ToList(); + + var headers = dataSource[0].Keys; + + var builder = new HtmlBuilder(HtmlTag.Div) + .WithCssClass("table-responsive"); + + builder.Append(HtmlTag.Table, table => + { + table.WithCssClass("table table-striped table-hover"); + + table.Append(HtmlTag.Thead, thead => + { + thead.Append(HtmlTag.Tr, tr => + { + foreach (var header in headers) + { + tr.Append(HtmlTag.Th, th => th.AppendText(header)); + } + }); + }); + + table.Append(HtmlTag.Tbody, tbody => + { + foreach (var row in dataSource) + { + tbody.Append(HtmlTag.Tr, tr => + { + foreach (var header in headers) + { + tr.Append(HtmlTag.Td, td => + { + if (row.TryGetValue(header, out var value)) + { + td.AppendText(value?.ToStringValue()); + } + else + { + td.AppendText(""); + } + }); + } + }); + } + }); + }); + + return new StringValue(builder.ToString(), encode: false); + }); + + private static bool IsImageFile(string? fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + return false; + + return Path.GetExtension(fileName).ToLowerInvariant() switch + { + ".png" => true, + ".jpg" => true, + ".jpeg" => true, + _ => false + }; + } + + private static T GetRequiredService(TemplateContext context) where T : notnull + { + if (!TryGetAmbientValue(context, ServiceProviderKey, out var serviceProvider)) + throw new InvalidOperationException("Service provider not available in HTML template context."); + + return serviceProvider.GetRequiredService(); + } + + private static bool TryGetAmbientValue(TemplateContext context, string key, out T value) + { + if (context.AmbientValues.TryGetValue(key, out var ambientValue) && ambientValue is T typedValue) + { + value = typedValue; + return true; + } + + value = default!; + return false; + } +} diff --git a/src/MasterData.Core/Html/Templates/HtmlTemplateRenderer.cs b/src/MasterData.Core/Html/Templates/HtmlTemplateRenderer.cs new file mode 100644 index 000000000..3b3cee7e9 --- /dev/null +++ b/src/MasterData.Core/Html/Templates/HtmlTemplateRenderer.cs @@ -0,0 +1,61 @@ +#nullable disable warnings +using System; +using System.Collections.Generic; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Fluid; +using JetBrains.Annotations; +using JJMasterData.Core.DataDictionary.Models; + +namespace JJMasterData.Core.Html.Templates; + +[PublicAPI] +public class HtmlTemplateRenderer( + FluidParser fluidParser, + IServiceProvider serviceProvider) +{ + public IFluidTemplate ParseTemplate(string template) + { + return fluidParser.Parse(template); + } + + public ValueTask RenderTemplate(string templateString, Dictionary values) + { + if (!fluidParser.TryParse(templateString, out var template, out var error)) + return new(error); + + var context = new HtmlTemplateContext(serviceProvider, values); + + return template.RenderAsync(context, HtmlEncoder.Default); + } + + public ValueTask RenderTemplate(string templateString, TemplateContext context) + { + if (!fluidParser.TryParse(templateString, out var template, out var error)) + return new(error); + + return template.RenderAsync(context, HtmlEncoder.Default); + } + + public ValueTask RenderTemplate(IFluidTemplate template, TemplateContext context) + { + context.AmbientValues[HtmlTemplateOptions.ServiceProviderKey] = serviceProvider; + + return template.RenderAsync(context, HtmlEncoder.Default); + } + + public ValueTask RenderTemplate(FormElement formElement, FormElementField field, Dictionary values) + { + var context = new HtmlTemplateContext(serviceProvider, values) + { + AmbientValues = + { + [HtmlTemplateOptions.FormElementKey] = formElement, + [HtmlTemplateOptions.FormElementFieldKey] = field, + [HtmlTemplateOptions.FormValuesKey] = values + } + }; + + return RenderTemplate(field.GridRenderingTemplate, context); + } +} diff --git a/src/MasterData.Core/Http/Abstractions/IClaimsPrincipalAcessor.cs b/src/MasterData.Core/Http/Abstractions/IClaimsPrincipalAcessor.cs deleted file mode 100644 index 20b1aeb7b..000000000 --- a/src/MasterData.Core/Http/Abstractions/IClaimsPrincipalAcessor.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Security.Claims; - -namespace JJMasterData.Core.Http.Abstractions; - -public interface IClaimsPrincipalAccessor -{ - ClaimsPrincipal User { get; } -} \ No newline at end of file diff --git a/src/MasterData.Core/Http/Abstractions/IFormValues.cs b/src/MasterData.Core/Http/Abstractions/IFormValues.cs deleted file mode 100644 index 0b6d768d0..000000000 --- a/src/MasterData.Core/Http/Abstractions/IFormValues.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace JJMasterData.Core.Http.Abstractions; - -public interface IFormValues -{ - public bool ContainsFormValues(); - string this[string key] { get; } - -#if NETFRAMEWORK - System.Web.HttpPostedFile GetFile(string file); - string GetUnvalidated(string key); -#elif NET - Microsoft.AspNetCore.Http.IFormFile GetFile(string file); -#else - // .NET Standard workaround, this is never compiled. - dynamic GetFile(string file); -#endif -} \ No newline at end of file diff --git a/src/MasterData.Core/Http/Abstractions/IHttpContext.cs b/src/MasterData.Core/Http/Abstractions/IHttpContext.cs deleted file mode 100644 index 35c305208..000000000 --- a/src/MasterData.Core/Http/Abstractions/IHttpContext.cs +++ /dev/null @@ -1,11 +0,0 @@ -#nullable enable -using System.Security.Claims; - -namespace JJMasterData.Core.Http.Abstractions; - -public interface IHttpContext -{ - IHttpSession Session { get; } - IHttpRequest Request { get; } - ClaimsPrincipal? User { get; } -} \ No newline at end of file diff --git a/src/MasterData.Core/Http/Abstractions/IHttpRequest.cs b/src/MasterData.Core/Http/Abstractions/IHttpRequest.cs deleted file mode 100644 index c42435a93..000000000 --- a/src/MasterData.Core/Http/Abstractions/IHttpRequest.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace JJMasterData.Core.Http.Abstractions; - -public interface IHttpRequest -{ - string UserHostAddress { get; } - string HttpMethod { get; } - string UserAgent { get; } - string AbsoluteUri { get; } - string ApplicationPath { get; } - string ApplicationUri { get; } - string this[string key] { get; } - public IQueryString QueryString { get; } - IFormValues Form { get; } - string ContentType { get; } - string Path { get; } -} \ No newline at end of file diff --git a/src/MasterData.Core/Http/Abstractions/IHttpSession.cs b/src/MasterData.Core/Http/Abstractions/IHttpSession.cs deleted file mode 100644 index 365c0217a..000000000 --- a/src/MasterData.Core/Http/Abstractions/IHttpSession.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace JJMasterData.Core.Http.Abstractions; - -public interface IHttpSession -{ - string this[string key] { get; set; } - void SetSessionValue(string key, object value); - T GetSessionValue(string key); - bool HasKey(string key); - bool HasSession(); -} \ No newline at end of file diff --git a/src/MasterData.Core/Http/Abstractions/IQueryString.cs b/src/MasterData.Core/Http/Abstractions/IQueryString.cs deleted file mode 100644 index 654b81bdd..000000000 --- a/src/MasterData.Core/Http/Abstractions/IQueryString.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace JJMasterData.Core.Http.Abstractions; - -public interface IQueryString -{ - string this[string key] { get; } - public string Value { get; } -} \ No newline at end of file diff --git a/src/MasterData.Core/Http/Abstractions/IRequestLengthService.cs b/src/MasterData.Core/Http/Abstractions/IRequestLengthService.cs deleted file mode 100644 index 36105d152..000000000 --- a/src/MasterData.Core/Http/Abstractions/IRequestLengthService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace JJMasterData.Core.Http.Abstractions; - -public interface IRequestLengthService -{ - public long GetMaxRequestBodySize(); -} diff --git a/src/MasterData.Core/Http/Abstractions/IUrlHelper.cs b/src/MasterData.Core/Http/Abstractions/IUrlHelper.cs deleted file mode 100644 index d49a67fe7..000000000 --- a/src/MasterData.Core/Http/Abstractions/IUrlHelper.cs +++ /dev/null @@ -1,11 +0,0 @@ -#if !NET - -namespace JJMasterData.Core.Http.Abstractions; - -public interface IUrlHelper -{ - string Action(string action = null, - string controller = null, - object values = null); -} -#endif diff --git a/src/MasterData.Core/Http/AspNetCore/ClaimsPrincipalWrapper.cs b/src/MasterData.Core/Http/AspNetCore/ClaimsPrincipalWrapper.cs deleted file mode 100644 index cc10dbd38..000000000 --- a/src/MasterData.Core/Http/AspNetCore/ClaimsPrincipalWrapper.cs +++ /dev/null @@ -1,13 +0,0 @@ -#nullable enable -#if NET -using System.Security.Claims; -using JJMasterData.Core.Http.Abstractions; -using Microsoft.AspNetCore.Http; - -namespace JJMasterData.Core.Http.AspNetCore; - -public class ClaimsPrincipalWrapper(IHttpContextAccessor httpContextAccessor) : IClaimsPrincipalAccessor -{ - public ClaimsPrincipal? User { get; } = httpContextAccessor.HttpContext?.User; -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/AspNetCore/FormValuesWrapper.cs b/src/MasterData.Core/Http/AspNetCore/FormValuesWrapper.cs deleted file mode 100644 index b85659b29..000000000 --- a/src/MasterData.Core/Http/AspNetCore/FormValuesWrapper.cs +++ /dev/null @@ -1,33 +0,0 @@ -#if NET - -#nullable enable - -using JJMasterData.Core.Http.Abstractions; -using Microsoft.AspNetCore.Http; - -namespace JJMasterData.Core.Http.AspNetCore; - -internal sealed class FormValuesWrapper(IHttpContextAccessor httpContextAccessor) : IFormValues -{ - private readonly HttpContext _httpContext = httpContextAccessor.HttpContext!; - - private IFormCollection? _formCollection; - - private IFormCollection? FormCollection - { - get - { - if (_formCollection == null && _httpContext.Request.HasFormContentType) - _formCollection = _httpContext.Request.Form; - - return _formCollection; - } - } - - public bool ContainsFormValues() => FormCollection is not null; - - public string? this[string key] => FormCollection?[key]; - - public IFormFile? GetFile(string file) => FormCollection?.Files[file]; -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/AspNetCore/HttpRequestWrapper.cs b/src/MasterData.Core/Http/AspNetCore/HttpRequestWrapper.cs deleted file mode 100644 index 85535bbab..000000000 --- a/src/MasterData.Core/Http/AspNetCore/HttpRequestWrapper.cs +++ /dev/null @@ -1,50 +0,0 @@ -#if NET -using System; -using JJMasterData.Core.Http.Abstractions; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; - -namespace JJMasterData.Core.Http.AspNetCore; - -internal sealed class HttpRequestWrapper( - IHttpContextAccessor httpContextAccessor, - IFormValues formValues, - IQueryString queryString) - : IHttpRequest -{ - public IQueryString QueryString { get; } = queryString; - public IFormValues Form { get; } = formValues; - - private HttpRequest Request => httpContextAccessor.HttpContext?.Request; - - private HttpContext HttpContext => httpContextAccessor.HttpContext; - - public string ApplicationUri => new Uri($"{Request.Scheme}://{Request.Host}{Request.PathBase}").ToString(); - public string this[string key] => GetValue(key); - - public string UserHostAddress => HttpContext?.Connection.RemoteIpAddress?.ToString(); - - public string HttpMethod => Request?.Method; - - public string UserAgent => Request?.Headers.UserAgent; - - public string AbsoluteUri => Request?.GetDisplayUrl(); - - public string ApplicationPath => Request?.PathBase; - - public string ContentType => Request?.ContentType; - public string Path => Request?.Path; - - private string GetValue(string key) - { - if (Request?.Query.ContainsKey(key) == true) - return Request.Query[key]; - - if (Request?.HasFormContentType == true) - return Request.Form[key]; - - return null; - } -} - -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/AspNetCore/HttpSessionWrapper.cs b/src/MasterData.Core/Http/AspNetCore/HttpSessionWrapper.cs deleted file mode 100644 index 59481e867..000000000 --- a/src/MasterData.Core/Http/AspNetCore/HttpSessionWrapper.cs +++ /dev/null @@ -1,36 +0,0 @@ -#if NET -using System; -using System.Linq; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; -using Microsoft.AspNetCore.Http; - -namespace JJMasterData.Core.Http.AspNetCore; - -internal sealed class HttpSessionWrapper(IHttpContextAccessor contextAccessor) : IHttpSession -{ - private readonly ISession _session = contextAccessor.HttpContext?.Session; - - public string this[string key] - { - get => _session.GetString(key); - set - { - if(value == null) - _session.Remove(key); - else - _session.SetString(key, value); - } - } - - public void SetSessionValue(string key, object value) => _session.SetObject(key, value); - - public T GetSessionValue(string key) => _session.GetObject(key); - public bool HasKey(string key) - { - return _session.Keys.Any(k=>k == key); - } - - public bool HasSession() => _session != null; -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/AspNetCore/QueryStringWrapper.cs b/src/MasterData.Core/Http/AspNetCore/QueryStringWrapper.cs deleted file mode 100644 index 0e93fc36d..000000000 --- a/src/MasterData.Core/Http/AspNetCore/QueryStringWrapper.cs +++ /dev/null @@ -1,16 +0,0 @@ -#if NET -using JJMasterData.Core.Http.Abstractions; -using Microsoft.AspNetCore.Http; - -namespace JJMasterData.Core.Http.AspNetCore; - -internal sealed class QueryStringWrapper(IHttpContextAccessor httpContextAccessor) : IQueryString -{ - private IQueryCollection QueryCollection { get; } = httpContextAccessor.HttpContext?.Request.Query; - private QueryString QueryString { get; } = httpContextAccessor.HttpContext?.Request.QueryString ?? new(); - - public string this[string key] => QueryCollection[key]; - - public string Value => QueryString.Value; -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/AspNetCore/RequestLengthService.cs b/src/MasterData.Core/Http/AspNetCore/RequestLengthService.cs deleted file mode 100644 index caa142f21..000000000 --- a/src/MasterData.Core/Http/AspNetCore/RequestLengthService.cs +++ /dev/null @@ -1,17 +0,0 @@ -#if NET -using JJMasterData.Core.Http.Abstractions; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.Options; - -namespace JJMasterData.Core.Http.AspNetCore; - -internal sealed class RequestLengthService(IOptions options) : IRequestLengthService -{ - private readonly long? _maxRequestBodySize = options.Value.MultipartBodyLengthLimit; - - public long GetMaxRequestBodySize() - { - return _maxRequestBodySize ?? 30720000; - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/HttpContextWrapper.cs b/src/MasterData.Core/Http/HttpContextWrapper.cs deleted file mode 100644 index 2faeedb24..000000000 --- a/src/MasterData.Core/Http/HttpContextWrapper.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Security.Claims; -using JJMasterData.Core.Http.Abstractions; - -namespace JJMasterData.Core.Http; - -internal sealed class HttpContextWrapper(IHttpSession session, IHttpRequest request, - IClaimsPrincipalAccessor claimsPrincipalAccessor) - : IHttpContext -{ - public IHttpSession Session { get; } = session; - public IHttpRequest Request { get; } = request; - public ClaimsPrincipal User { get; } = claimsPrincipalAccessor.User; -} diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebClaimsPrincipalWrapper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebClaimsPrincipalWrapper.cs deleted file mode 100644 index b48f11107..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebClaimsPrincipalWrapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -#if NETFRAMEWORK -using System.Security.Claims; -using System.Web; -using JJMasterData.Core.Http.Abstractions; - -namespace JJMasterData.Core.Http.SystemWeb; - -public class SystemWebClaimsPrincipalWrapper : IClaimsPrincipalAccessor -{ - public ClaimsPrincipal User { get; } - - public SystemWebClaimsPrincipalWrapper() - { - if (HttpContext.Current == null) - return; - if (HttpContext.Current.User == null) - return; - - User = HttpContext.Current.User as ClaimsPrincipal; - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebFormValuesWrapper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebFormValuesWrapper.cs deleted file mode 100644 index d0a099df1..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebFormValuesWrapper.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Specialized; -using System.Web; -using JJMasterData.Core.Http.Abstractions; - -#if NET48 - -namespace JJMasterData.Core.Http.SystemWeb; - -internal sealed class SystemWebFormValuesWrapper : IFormValues -{ - private static UnvalidatedRequestValues UnvalidatedFormCollection => HttpContext.Request.Unvalidated; - private static NameValueCollection FormCollection => HttpContext.Request.Form; - private static HttpContext HttpContext => HttpContext.Current; - - public bool ContainsFormValues() => FormCollection is { Count: > 0 }; - public string this[string key] => FormCollection?[key]; - public HttpPostedFile GetFile(string file) - { - return HttpContext?.Request.Files[file]; - } - public string GetUnvalidated(string key) - { - return UnvalidatedFormCollection[key]; - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebHelper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebHelper.cs deleted file mode 100644 index 4902ec8f6..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebHelper.cs +++ /dev/null @@ -1,54 +0,0 @@ -#if NET48 - -using System.IO; -using System.Web; -using JJMasterData.Commons.Util; -using JJMasterData.Core.UI.Components; - -namespace JJMasterData.Core.Http.SystemWeb; - -public static class SystemWebHelper -{ - public static bool CanSendResult(ComponentResult result) - { - return result is not EmptyComponentResult && result is not RenderedComponentResult; - } - - public static void SendResult(ComponentResult result) - { - var currentContext = System.Web.HttpContext.Current; - - if (result is RedirectComponentResult redirectComponentResult) - currentContext.Response.Redirect(redirectComponentResult.Content); - else if (result is FileComponentResult fileComponentResult) - { - var filePath = fileComponentResult.Content; - var fileName = Path.GetFileName(filePath); - - var file = new MemoryStream(File.ReadAllBytes(filePath)); - currentContext.Response.ClearHeaders(); - currentContext.Response.ClearContent(); - currentContext.Response.ContentType = MimeTypeUtil.GetMimeType(fileName); - currentContext.Response.AddHeader("Content-Transfer-Encoding", "binary"); - currentContext.Response.AddHeader("Content-Description", "File Transfer"); - currentContext.Response.AddHeader("Content-Disposition", - $"attachment; filename={HttpUtility.UrlEncode(fileName)}"); - currentContext.Response.AddHeader("Content-Length", file.Length.ToString()); - currentContext.Response.BinaryWrite(file.ToArray()); - currentContext.Response.End(); - } - else - { - if (result is JsonComponentResult) - { - currentContext.Response.ContentType = "application/json"; - } - - currentContext.Response.Clear(); - currentContext.Response.StatusCode = result.StatusCode; - currentContext.Response.Write(result.Content!); - currentContext.Response.End(); - } - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebHttpRequestWrapper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebHttpRequestWrapper.cs deleted file mode 100644 index e555304a5..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebHttpRequestWrapper.cs +++ /dev/null @@ -1,40 +0,0 @@ -#if NETFRAMEWORK - -using System; -using System.Web; -using System.Web.Mvc; -using JJMasterData.Core.Http.Abstractions; - -namespace JJMasterData.Core.Http.SystemWeb; - -internal sealed class SystemWebHttpRequestWrapper(IQueryString queryString, IFormValues form) : IHttpRequest -{ - private static HttpRequest Request => HttpContext.Current.Request; - public string UserHostAddress => Request.UserHostAddress; - public string HttpMethod=> Request.HttpMethod; - public string UserAgent => Request.UserAgent; - public string AbsoluteUri => Request.Url.AbsoluteUri; - public string ApplicationPath=> Request.ApplicationPath; - - public string ApplicationUri - { - get - { - var request = HttpContext.Current.Request; - var uri = new Uri($"{request.Url.Scheme}://{request.Url.Authority}{new UrlHelper(request.RequestContext).Content("~")}"); - - if(!request.IsLocal) - return uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, - UriFormat.UriEscaped); - - return uri.ToString(); - } - } - public IFormValues Form => form; - public IQueryString QueryString { get; } = queryString; - public string ContentType => Request.ContentType; - public string Path => Request.Path; - - public string this[string key] => Request[key]; -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebHttpSessionWrapper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebHttpSessionWrapper.cs deleted file mode 100644 index 8283d0d0e..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebHttpSessionWrapper.cs +++ /dev/null @@ -1,47 +0,0 @@ -#if NETFRAMEWORK -using System; -using System.Web; -using System.Web.SessionState; -using JJMasterData.Core.Http.Abstractions; - -namespace JJMasterData.Core.Http.SystemWeb; - -internal sealed class SystemWebHttpSessionWrapper : IHttpSession -{ - private static HttpSessionState Session => HttpContext.Current.Session; - public string this[string key] - { - get => Session[key]?.ToString(); - set => Session[key] = value; - } - - public void SetSessionValue(string key, object value) => Session[key] = value; - - public T GetSessionValue(string key) => (T)Session[key]; - public bool HasKey(string key) - { - foreach (var existingKey in Session.Keys) - { - if(string.IsNullOrEmpty(existingKey?.ToString())) - continue; - - if(string.Equals(existingKey.ToString(), key)) - return true; - } - - return false; - } - - public bool HasSession() - { - try - { - return Session != null; - } - catch - { - return false; - } - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebQueryStringWrapper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebQueryStringWrapper.cs deleted file mode 100644 index b03f4a37e..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebQueryStringWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Specialized; -using System.Web; -using JJMasterData.Core.Http.Abstractions; - -#if NETFRAMEWORK -namespace JJMasterData.Core.Http.SystemWeb; - -internal sealed class SystemWebQueryStringWrapper : IQueryString -{ - private static NameValueCollection QueryString => HttpContext.Current.Request.QueryString; - public string this[string key] => QueryString[key]; - public string Value => QueryString.ToString(); -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebRequestLengthService.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebRequestLengthService.cs deleted file mode 100644 index f245eb4aa..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebRequestLengthService.cs +++ /dev/null @@ -1,30 +0,0 @@ -#if NETFRAMEWORK -using JJMasterData.Core.Http.Abstractions; - -namespace JJMasterData.Core.Http.SystemWeb; - -internal sealed class SystemWebRequestLengthService : IRequestLengthService -{ - private readonly long? _maxRequestBodySize; - - public SystemWebRequestLengthService() - { - var maxRequestLengthInKb = GetMaxRequestLengthFromWebConfig(); - _maxRequestBodySize = maxRequestLengthInKb * 1024L; - } - - public long GetMaxRequestBodySize() - { - return _maxRequestBodySize ?? 4194304; - } - - private static int? GetMaxRequestLengthFromWebConfig() - { - var maxRequestLength = 4194304; //4mb - if (System.Configuration.ConfigurationManager.GetSection("system.web/httpRuntime") is System.Web.Configuration.HttpRuntimeSection section) - maxRequestLength = section.MaxRequestLength * 1024; - - return maxRequestLength; - } -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Http/SystemWeb/SystemWebUrlHelperWrapper.cs b/src/MasterData.Core/Http/SystemWeb/SystemWebUrlHelperWrapper.cs deleted file mode 100644 index e47cddb59..000000000 --- a/src/MasterData.Core/Http/SystemWeb/SystemWebUrlHelperWrapper.cs +++ /dev/null @@ -1,95 +0,0 @@ -#nullable enable -#if !NET -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using JetBrains.Annotations; -using JJMasterData.Core.Configuration.Options; -using JJMasterData.Core.Http.Abstractions; -using Microsoft.Extensions.Options; - -namespace JJMasterData.Core.Http.SystemWeb; - -public class SystemWebUrlHelperWrapper(IHttpRequest httpRequest, IOptionsSnapshot options) - : IUrlHelper -{ - private IHttpRequest HttpRequest { get; } = httpRequest; - private string? MasterDataUrl { get; } = options.Value.MasterDataUrl; - private bool EnableCultureProvider { get; } = options.Value.EnableCultureProviderAtUrl; - - public string Action([AspMvcAction]string? action = null, [AspMvcController] string? controller = - null, object? values = null) - { - - string baseUrl; - - if (MasterDataUrl is null || string.IsNullOrEmpty(MasterDataUrl)) - { - var appPath = HttpRequest.ApplicationPath; - - baseUrl = string.IsNullOrEmpty(appPath) ? "/" : appPath; - } - else - { - baseUrl = MasterDataUrl; - } - - if (!baseUrl.EndsWith("/")) - { - baseUrl += "/"; - } - - var valuesDictionary = new Dictionary(); - - if (values != null) - { - valuesDictionary = values.GetType().GetProperties() - .ToDictionary(prop => prop.Name, prop => prop.GetValue(values)?.ToString()); - } - - if(valuesDictionary.TryGetValue("elementName", out var elementName)) - { - valuesDictionary.Remove("elementName"); - } - - if(valuesDictionary.TryGetValue("Area", out var areaValue)) - { - valuesDictionary.Remove("Area"); - } - - var url = baseUrl; - - if(EnableCultureProvider) - url += $"{CultureInfo.CurrentUICulture}/"; - - if (!string.IsNullOrEmpty(areaValue)) - { - url += $"{areaValue}/"; - } - - if (!string.IsNullOrEmpty(controller)) - { - url += $"{controller}/"; - } - - if (!string.IsNullOrEmpty(action)) - { - url += $"{action}/"; - } - - if (!string.IsNullOrEmpty(elementName)) - { - url += $"{elementName}"; - } - - if (valuesDictionary.Count > 0) - { - url += $"?{string.Join("&", valuesDictionary.Select(kv => $"{kv.Key}={kv.Value}"))}"; - } - - - return url; - } - -} -#endif \ No newline at end of file diff --git a/src/MasterData.Core/Logging/LogMessages.cs b/src/MasterData.Core/Logging/LogMessages.cs index d603f81e2..4d0aa651b 100644 --- a/src/MasterData.Core/Logging/LogMessages.cs +++ b/src/MasterData.Core/Logging/LogMessages.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using Microsoft.Extensions.Logging; namespace JJMasterData.Core.Logging; diff --git a/src/MasterData.Core/Logging/LoggerExtensions.cs b/src/MasterData.Core/Logging/LoggerExtensions.cs index ca40990ff..94426d1fb 100644 --- a/src/MasterData.Core/Logging/LoggerExtensions.cs +++ b/src/MasterData.Core/Logging/LoggerExtensions.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using System.Collections.Generic; using JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/MasterData.Core.csproj b/src/MasterData.Core/MasterData.Core.csproj index 61c7429ca..8b11405a0 100644 --- a/src/MasterData.Core/MasterData.Core.csproj +++ b/src/MasterData.Core/MasterData.Core.csproj @@ -1,33 +1,30 @@ - net4.8;net10.0 + net10.0 latest 10.0 - disable - false JJMasterData.Core - Sun Version JJMasterData library to render JJMasterData's components. https://github.com/JJConsulting/JJMasterData JJMasterData.Core JJMasterData.Core + enable true + $(NoWarn);CS9107 - - - - - - - + + + + @@ -73,7 +70,7 @@ ComponentResult.cs - + ComponentResult.cs diff --git a/src/MasterData.Core/Tasks/AsyncHelper.cs b/src/MasterData.Core/Tasks/AsyncHelper.cs deleted file mode 100644 index 8d3cd76e5..000000000 --- a/src/MasterData.Core/Tasks/AsyncHelper.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -// ReSharper disable AsyncVoidLambda - -namespace JJMasterData.Core.Tasks; - -/// -/// Class to safely run async methods on sync environments like ASP.NET without deadlocks. -/// -public static class AsyncHelper -{ - /// - /// Execute is an async Task method which has a void return value synchronously - /// - /// Task method to execute. - public static void RunSync(Func task) - { - var oldContext = SynchronizationContext.Current; - var synch = new ExclusiveSynchronizationContext(); - SynchronizationContext.SetSynchronizationContext(synch); - synch.Post(async _ => - { - try - { - await task(); - } - catch (Exception e) - { - synch.InnerException = e; - throw; - } - finally - { - synch.EndMessageLoop(); - } - }, null); - synch.BeginMessageLoop(); - - SynchronizationContext.SetSynchronizationContext(oldContext); - } - - /// - /// Execute is an async Task method which has a T return type synchronously - /// - /// Return Type - /// Task method to execute - public static T RunSync(Func> task) - { - var oldContext = SynchronizationContext.Current; - var synch = new ExclusiveSynchronizationContext(); - SynchronizationContext.SetSynchronizationContext(synch); - var ret = default(T); - synch.Post(async _ => - { - try - { - ret = await task(); - } - catch (Exception e) - { - synch.InnerException = e; - throw; - } - finally - { - synch.EndMessageLoop(); - } - }, null); - synch.BeginMessageLoop(); - SynchronizationContext.SetSynchronizationContext(oldContext); - return ret; - } - - public static void RunSync(Func task) - { - RunSync(()=>task().AsTask()); - } - - public static T RunSync(Func> task) - { - return RunSync(()=>task().AsTask()); - } - - private sealed class ExclusiveSynchronizationContext : SynchronizationContext - { - private bool done; - public Exception InnerException { get; set; } - readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false); - readonly Queue> items = new(); - - public override void Send(SendOrPostCallback d, object state) - { - throw new NotSupportedException("We cannot send to our same thread"); - } - - public override void Post(SendOrPostCallback d, object state) - { - lock (items) - { - items.Enqueue(Tuple.Create(d, state)); - } - workItemsWaiting.Set(); - } - - public void EndMessageLoop() - { - Post(_ => done = true, null); - } - - public void BeginMessageLoop() - { - while (!done) - { - Tuple task = null; - lock (items) - { - if (items.Count > 0) - { - task = items.Dequeue(); - } - } - if (task != null) - { - task.Item1(task.Item2); - if (InnerException != null) // the method threw an exeption - { - throw new AggregateException("AsyncHelper.Run method threw an exception.", InnerException); - } - } - else - { - workItemsWaiting.WaitOne(); - } - } - } - - public override SynchronizationContext CreateCopy() - { - return this; - } - } -} \ No newline at end of file diff --git a/src/MasterData.Core/Tasks/ValueTaskHelper.cs b/src/MasterData.Core/Tasks/ValueTaskHelper.cs deleted file mode 100644 index ed12d8b8a..000000000 --- a/src/MasterData.Core/Tasks/ValueTaskHelper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Threading.Tasks; - -namespace JJMasterData.Core.Tasks; - -internal static class ValueTaskHelper -{ - public static ValueTask CompletedTask - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { -#if NET - return ValueTask.CompletedTask; -#else - return default; -#endif - } - } -} \ No newline at end of file diff --git a/src/MasterData.Core/UI/Components/Actions/ActionButtonFactory.cs b/src/MasterData.Core/UI/Components/Actions/ActionButtonFactory.cs index 0186e1f76..0ef53eb5c 100644 --- a/src/MasterData.Core/UI/Components/Actions/ActionButtonFactory.cs +++ b/src/MasterData.Core/UI/Components/Actions/ActionButtonFactory.cs @@ -1,5 +1,3 @@ -#nullable enable - using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Commons.Exceptions; using JJMasterData.Commons.Security.Cryptography.Abstractions; diff --git a/src/MasterData.Core/UI/Components/Actions/ActionContext.cs b/src/MasterData.Core/UI/Components/Actions/ActionContext.cs index 9023e8f01..9299bcc2d 100644 --- a/src/MasterData.Core/UI/Components/Actions/ActionContext.cs +++ b/src/MasterData.Core/UI/Components/Actions/ActionContext.cs @@ -1,5 +1,3 @@ -#nullable enable - using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; diff --git a/src/MasterData.Core/UI/Components/Actions/ActionData.cs b/src/MasterData.Core/UI/Components/Actions/ActionData.cs index c1190e414..8f705b605 100644 --- a/src/MasterData.Core/UI/Components/Actions/ActionData.cs +++ b/src/MasterData.Core/UI/Components/Actions/ActionData.cs @@ -1,9 +1,4 @@ -#nullable enable - - -using System.Text.Json; using System.Text.Json.Serialization; -using System.Xml; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Actions/ActionMap.cs b/src/MasterData.Core/UI/Components/Actions/ActionMap.cs index 07a90cf9e..cdd9d1851 100644 --- a/src/MasterData.Core/UI/Components/Actions/ActionMap.cs +++ b/src/MasterData.Core/UI/Components/Actions/ActionMap.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using JJMasterData.Commons.Exceptions; diff --git a/src/MasterData.Core/UI/Components/Actions/ActionScripts.cs b/src/MasterData.Core/UI/Components/Actions/ActionScripts.cs index 3721497a6..e643ebe3b 100644 --- a/src/MasterData.Core/UI/Components/Actions/ActionScripts.cs +++ b/src/MasterData.Core/UI/Components/Actions/ActionScripts.cs @@ -1,4 +1,4 @@ -using System; +#nullable disable warnings using System.Collections.Generic; using System.Text; using System.Web; @@ -9,8 +9,6 @@ using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; @@ -66,7 +64,7 @@ private string GetInternalUrlScript(InternalAction action, ActionContext actionC new { Area = "MasterData", - parameters = encryptionService.EncryptStringWithUrlEscape(@params.ToString()) + parameters = encryptionService.EncryptString(@params.ToString()) }); return @@ -100,10 +98,10 @@ private string GetUrlRedirectScript( ActionSource actionSource ) { - string confirmationMessage = + var confirmationMessage = GetParsedConfirmationMessage(stringLocalizer[action.ConfirmationMessage ?? string.Empty], actionContext.FormStateData); - string isOpenNewTabPage = action.OpenInNewTab ? "true" : "false"; + var isOpenNewTabPage = action.OpenInNewTab ? "true" : "false"; if (actionSource is ActionSource.Field or ActionSource.FormToolbar) { @@ -119,11 +117,12 @@ ActionSource actionSource } var script = new StringBuilder(); - string url = urlRedirectService.GetParsedUrl(action, actionContext.FormStateData); - string isModal = action.IsModal ? "true" : "false"; - string isIframe = action.IsIframe ? "true" : "false"; + var url = HttpUtility.JavaScriptStringEncode(urlRedirectService.GetParsedUrl(action, actionContext.FormStateData)); + var isModal = action.IsModal ? "true" : "false"; + var isIframe = action.IsIframe ? "true" : "false"; - string modalTitle = action.ModalTitle; + var modalTitle = HttpUtility.JavaScriptStringEncode( + urlRedirectService.GetParsedModalTitle(action, actionContext.FormStateData)); script.Append("ActionHelper.executeClientSideRedirect('"); script.Append(url); diff --git a/src/MasterData.Core/UI/Components/AsyncComponent.cs b/src/MasterData.Core/UI/Components/AsyncComponent.cs index 5092dcfda..dbf7b659e 100644 --- a/src/MasterData.Core/UI/Components/AsyncComponent.cs +++ b/src/MasterData.Core/UI/Components/AsyncComponent.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.Threading.Tasks; using JJConsulting.Html.Bootstrap.Abstractions; diff --git a/src/MasterData.Core/UI/Components/AuditLog/AuditLogViewFactory.cs b/src/MasterData.Core/UI/Components/AuditLog/AuditLogViewFactory.cs index 37e24d473..451fe5c64 100644 --- a/src/MasterData.Core/UI/Components/AuditLog/AuditLogViewFactory.cs +++ b/src/MasterData.Core/UI/Components/AuditLog/AuditLogViewFactory.cs @@ -5,13 +5,12 @@ using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; internal sealed class AuditLogViewFactory( - IHttpContext httpContext, + IHttpContextAccessor httpContext, IMasterDataUser masterDataUser, IEntityRepository entityRepository, AuditLogService auditLogService, diff --git a/src/MasterData.Core/UI/Components/AuditLog/JJAuditLogView.cs b/src/MasterData.Core/UI/Components/AuditLog/JJAuditLogView.cs index ce83a0209..3abfa2037 100644 --- a/src/MasterData.Core/UI/Components/AuditLog/JJAuditLogView.cs +++ b/src/MasterData.Core/UI/Components/AuditLog/JJAuditLogView.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; @@ -18,10 +19,6 @@ using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.Tasks; - using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; @@ -42,7 +39,7 @@ private RouteContext RouteContext if (field != null) return field; - var factory = new RouteContextFactory(CurrentContext.Request.QueryString, EncryptionService); + var factory = new RouteContextFactory(CurrentContext, EncryptionService); field = factory.Create(); return field; @@ -50,17 +47,10 @@ private RouteContext RouteContext } private ComponentContext ComponentContext => RouteContext.ComponentContext; - - /// - /// Id do usuário Atual - /// - /// - /// Se a variavel não for atribuida diretamente, - /// o sistema tenta recuperar em UserValues ou nas variaveis de Sessão - /// + internal string UserId => _masterDataUser.Id; - private IHttpContext CurrentContext { get; } + private IHttpContextAccessor CurrentContext { get; } private AuditLogService AuditLogService { get; } private IEncryptionService EncryptionService { get; } @@ -88,7 +78,7 @@ private JJDataPanel DataPanel public JJAuditLogView( FormElement formElement, - IHttpContext currentContext, + IHttpContextAccessor currentContext, IMasterDataUser masterDataUser, IEntityRepository entityRepository, AuditLogService auditLogService, @@ -109,7 +99,7 @@ public JJAuditLogView( protected override async Task BuildResultAsync() { - var logId = CurrentContext.Request.Form[$"audit-log-id-{FormElement.Name}"]; + var logId = CurrentContext.HttpContext!.Request.GetFormValue($"audit-log-id-{FormElement.Name}"); var html = new HtmlBuilder(HtmlTag.Div); if (string.IsNullOrEmpty(logId)) @@ -323,7 +313,7 @@ private JJGridView CreateGridViewLog() }; alert.Messages.Add(StringLocalizer["Audit Log is disabled. Please contact the administrator."]); args.HtmlBuilder.AppendComponent(alert); - return ValueTaskHelper.CompletedTask; + return ValueTask.CompletedTask; }; } @@ -446,4 +436,4 @@ private async Task GetLogListGroupHtml(string recordsKey, string vi return html; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/CollapsePanel/JJMasterDataCollapsePanel.cs b/src/MasterData.Core/UI/Components/CollapsePanel/JJMasterDataCollapsePanel.cs index 93ce115bf..ddb4e367d 100644 --- a/src/MasterData.Core/UI/Components/CollapsePanel/JJMasterDataCollapsePanel.cs +++ b/src/MasterData.Core/UI/Components/CollapsePanel/JJMasterDataCollapsePanel.cs @@ -1,24 +1,26 @@ using JJConsulting.Html.Bootstrap.Components; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; internal sealed class JJMasterDataCollapsePanel : JJCollapsePanel { - public JJMasterDataCollapsePanel(IFormValues formValues) + public JJMasterDataCollapsePanel(IHttpContextAccessor httpContextAccessor) { - if (formValues.TryGetValue($"{Name}-is-open", out var value)) + var request = httpContextAccessor.HttpContext?.Request; + if (request?.HasFormContentType == true && + request.Form.TryGetValue($"{Name}-is-open", out var value)) { - IsOpen = "1".Equals(value) ? true : null; + IsOpen = "1".Equals(value.ToString()) ? true : null; } } - public JJMasterDataCollapsePanel(IFormValues formValues, string name) + public JJMasterDataCollapsePanel(IHttpContextAccessor httpContextAccessor, string name) { Name = name; - if (formValues.TryGetValue($"{Name}-is-open", out var value)) + var request = httpContextAccessor.HttpContext?.Request; + if (request?.HasFormContentType == true && + request.Form.TryGetValue($"{Name}-is-open", out var value)) { - IsOpen = "1".Equals(value) ; + IsOpen = "1".Equals(value.ToString()) ; } } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/ComponentFactory.cs b/src/MasterData.Core/UI/Components/ComponentFactory.cs index 58a17e4b0..06963cb4a 100644 --- a/src/MasterData.Core/UI/Components/ComponentFactory.cs +++ b/src/MasterData.Core/UI/Components/ComponentFactory.cs @@ -1,7 +1,4 @@ -#nullable enable - -using System; -using JJConsulting.Html.Bootstrap.Components; +using System; using JJMasterData.Core.UI.Components.Factories; using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.DependencyInjection; diff --git a/src/MasterData.Core/UI/Components/ComponentResult.cs b/src/MasterData.Core/UI/Components/ComponentResult.cs index bb0fc6512..89f0ae353 100644 --- a/src/MasterData.Core/UI/Components/ComponentResult.cs +++ b/src/MasterData.Core/UI/Components/ComponentResult.cs @@ -1,5 +1,3 @@ -#nullable enable - namespace JJMasterData.Core.UI.Components; public abstract class ComponentResult diff --git a/src/MasterData.Core/UI/Components/ContentComponentResult.cs b/src/MasterData.Core/UI/Components/ContentComponentResult.cs index cc90192dc..06b9f9db1 100644 --- a/src/MasterData.Core/UI/Components/ContentComponentResult.cs +++ b/src/MasterData.Core/UI/Components/ContentComponentResult.cs @@ -1,10 +1,7 @@ -#nullable enable - using System.Threading.Tasks; using JJConsulting.Html; #if NET -using Microsoft.AspNetCore.Mvc; #endif namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Controls/CheckBox/CheckboxFactory.cs b/src/MasterData.Core/UI/Components/Controls/CheckBox/CheckboxFactory.cs index e2d5bad3a..11170df32 100644 --- a/src/MasterData.Core/UI/Components/Controls/CheckBox/CheckboxFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/CheckBox/CheckboxFactory.cs @@ -1,11 +1,11 @@ +#nullable disable warnings using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; -internal sealed class CheckboxFactory(IFormValues formValues, IStringLocalizer stringLocalizer) +internal sealed class CheckboxFactory(IHttpContextAccessor formValues, IStringLocalizer stringLocalizer) : IControlFactory { public JJCheckBox Create() => new(formValues,stringLocalizer); diff --git a/src/MasterData.Core/UI/Components/Controls/CheckBox/JJCheckBox.cs b/src/MasterData.Core/UI/Components/Controls/CheckBox/JJCheckBox.cs index 29547f152..0405ce3a9 100644 --- a/src/MasterData.Core/UI/Components/Controls/CheckBox/JJCheckBox.cs +++ b/src/MasterData.Core/UI/Components/Controls/CheckBox/JJCheckBox.cs @@ -1,11 +1,8 @@ -using System.Threading.Tasks; +#nullable disable warnings +using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; - using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -31,7 +28,7 @@ public bool IsChecked { get { - if (_isChecked == null && FormValues.ContainsFormValues()) + if (_isChecked == null && HasFormValues) _isChecked = Value.Equals(FormValues[Name]); return _isChecked ?? false; @@ -39,7 +36,7 @@ public bool IsChecked set => _isChecked = value; } - public JJCheckBox(IFormValues formValues, IStringLocalizer stringLocalizer) : base(formValues) + public JJCheckBox(IHttpContextAccessor formValues, IStringLocalizer stringLocalizer) : base(formValues) { _stringLocalizer = stringLocalizer; Visible = true; @@ -133,4 +130,4 @@ private HtmlBuilder GetInputHtml() return div; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Controls/CodeEditor/CodeEditorFactory.cs b/src/MasterData.Core/UI/Components/Controls/CodeEditor/CodeEditorFactory.cs index cf49e3564..8d25687a0 100644 --- a/src/MasterData.Core/UI/Components/Controls/CodeEditor/CodeEditorFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/CodeEditor/CodeEditorFactory.cs @@ -1,9 +1,9 @@ +#nullable disable warnings using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -public class CodeEditorFactory(IFormValues formValues) : IControlFactory +public class CodeEditorFactory(IHttpContextAccessor formValues) : IControlFactory { public JJCodeEditor Create() { diff --git a/src/MasterData.Core/UI/Components/Controls/CodeEditor/JJCodeEditor.cs b/src/MasterData.Core/UI/Components/Controls/CodeEditor/JJCodeEditor.cs index 7cf5973e3..7b692cc17 100644 --- a/src/MasterData.Core/UI/Components/Controls/CodeEditor/JJCodeEditor.cs +++ b/src/MasterData.Core/UI/Components/Controls/CodeEditor/JJCodeEditor.cs @@ -1,16 +1,12 @@ -#nullable enable - using System.Globalization; using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -public class JJCodeEditor(IFormValues formValues) : ControlBase(formValues) +public class JJCodeEditor(IHttpContextAccessor formValues) : ControlBase(formValues) { public string Language { get; set; } = "html"; public int Height { get; set; } = 300; diff --git a/src/MasterData.Core/UI/Components/Controls/ColorPicker/ColorPickerFactory.cs b/src/MasterData.Core/UI/Components/Controls/ColorPicker/ColorPickerFactory.cs index 60e22761c..06a3d1e87 100644 --- a/src/MasterData.Core/UI/Components/Controls/ColorPicker/ColorPickerFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/ColorPicker/ColorPickerFactory.cs @@ -1,9 +1,9 @@ +#nullable disable warnings using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components.ColorPicker; -internal sealed class ColorPickerFactory(IFormValues formValues) : IControlFactory +internal sealed class ColorPickerFactory(IHttpContextAccessor formValues) : IControlFactory { public JJColorPicker Create() { diff --git a/src/MasterData.Core/UI/Components/Controls/ColorPicker/JJColorPicker.cs b/src/MasterData.Core/UI/Components/Controls/ColorPicker/JJColorPicker.cs index 71c6b1216..8c64d4346 100644 --- a/src/MasterData.Core/UI/Components/Controls/ColorPicker/JJColorPicker.cs +++ b/src/MasterData.Core/UI/Components/Controls/ColorPicker/JJColorPicker.cs @@ -1,13 +1,12 @@ +#nullable disable warnings using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components.ColorPicker; -public class JJColorPicker(IFormValues formValues) : ControlBase(formValues) +public class JJColorPicker(IHttpContextAccessor formValues) : ControlBase(formValues) { public string Title { get; set; } diff --git a/src/MasterData.Core/UI/Components/Controls/ComboBox/ComboBoxFactory.cs b/src/MasterData.Core/UI/Components/Controls/ComboBox/ComboBoxFactory.cs index af507755b..a7b0043f4 100644 --- a/src/MasterData.Core/UI/Components/Controls/ComboBox/ComboBoxFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/ComboBox/ComboBoxFactory.cs @@ -1,14 +1,13 @@ +#nullable disable warnings using System; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; namespace JJMasterData.Core.UI.Components; internal sealed class ComboBoxFactory( - IFormValues formValues, + IHttpContextAccessor formValues, DataItemService dataItemService, IStringLocalizer stringLocalizer) : IControlFactory diff --git a/src/MasterData.Core/UI/Components/Controls/ComboBox/JJComboBox.cs b/src/MasterData.Core/UI/Components/Controls/ComboBox/JJComboBox.cs index ffbbaf184..a87cae746 100644 --- a/src/MasterData.Core/UI/Components/Controls/ComboBox/JJComboBox.cs +++ b/src/MasterData.Core/UI/Components/Controls/ComboBox/JJComboBox.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Linq; @@ -11,13 +9,12 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; public class JJComboBox( - IFormValues formValues, + IHttpContextAccessor formValues, DataItemService dataItemService, IStringLocalizer stringLocalizer) : ControlBase(formValues), IDataItemControl, IFloatingLabelControl @@ -39,7 +36,7 @@ public string? SelectedValue { get { - if (field == null && FormValues.ContainsFormValues()) + if (field == null && HasFormValues) { field = FormValues[Name]; } @@ -70,16 +67,13 @@ private HtmlBuilder GetSelectHtml(List values) { var select = new HtmlBuilder(HtmlTag.Select) .WithCssClass(CssClass) - .WithCssClass("form-control") - .WithCssClass(MultiSelect || DataItem.ShowIcon ? "selectpicker" : "form-select") + .WithCssClass("form-control form-select tom-select") .WithName(Name) .WithId(Id ?? Name) .WithAttributeIf(MultiSelect, "multiple") .WithAttributeIf(MultiSelect, "multiselect", "multiselect") - .WithAttributeIf(MultiSelect || DataItem.ShowIcon, "data-none-selected-text", GetFirstOptionText()) + .WithAttribute("data-placeholder", GetFirstOptionText()) .WithAttributeIf(!Enabled, "disabled") - .WithAttributeIf(BootstrapHelper.Version is 3, "data-style", "form-control") - .WithAttributeIf(BootstrapHelper.Version is 5, "data-style-base", "form-select form-dropdown") .WithAttributes(Attributes) .AppendRange(GetOptions(values)); @@ -168,7 +162,7 @@ private HtmlBuilder CreateOption(DataItemValue value) var content = new HtmlBuilder(); if (DataItem.ShowIcon) - content.AppendComponent(new JJIcon(value.Icon, value.IconColor)); + content.AppendComponent(new JJIcon(value.Icon.GetValueOrDefault(), value.IconColor ?? string.Empty)); var span = new HtmlBuilder(HtmlTag.Span); span.AppendText(label); @@ -187,8 +181,7 @@ private HtmlBuilder CreateOption(DataItemValue value) if (DataItem.ShowIcon) option.WithAttribute("data-content", content.ToString()); - if (!DataItem.ShowIcon) - option.AppendText(label); + option.AppendText(label); return option; } @@ -211,16 +204,16 @@ private IEnumerable GetReadOnlyInputs(IEnumerable va .WithNameAndId($"cboview_{Name}") .WithCssClass("form-control form-select") .WithCssClass(CssClass) - .WithValue(selectedText) + .WithValue(selectedText!) .WithAttributes(Attributes) .WithAttribute("readonly", "readonly"); yield return readonlyInput; } - private string GetSelectedText(IEnumerable list) + private string? GetSelectedText(IEnumerable list) { - string selectedText = string.Empty; + string? selectedText = string.Empty; if (SelectedValue == null) return selectedText; @@ -250,7 +243,7 @@ public Task> GetValuesAsync() /// public async Task GetDescriptionAsync() { - string description; + string? description; var item = await GetValueAsync(SelectedValue); if (item == null) return null; @@ -262,7 +255,7 @@ public Task> GetValuesAsync() { var div = new HtmlBuilder(HtmlTag.Div); - var icon = new JJIcon(item.Icon, item.IconColor, item.Description) + var icon = new JJIcon(item.Icon.GetValueOrDefault(), item.IconColor ?? string.Empty, item.Description ?? string.Empty) { CssClass = "fa-lg fa-fw" }.GetHtmlBuilder(); diff --git a/src/MasterData.Core/UI/Components/Controls/ControlBase.cs b/src/MasterData.Core/UI/Components/Controls/ControlBase.cs index 7aaf980b7..c9219ef99 100644 --- a/src/MasterData.Core/UI/Components/Controls/ControlBase.cs +++ b/src/MasterData.Core/UI/Components/Controls/ControlBase.cs @@ -1,21 +1,26 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Abstractions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -public abstract class ControlBase(IFormValues formValues) : ComponentBase +public abstract class ControlBase : ComponentBase { + protected ControlBase(IHttpContextAccessor httpContextAccessor) + { + HttpContextAccessor = httpContextAccessor; + } + /// /// Property to check if the control is enabled. /// (Default = true) /// public bool Enabled { get; set; } = true; - public Dictionary UserValues { get; set; } = new(); + public Dictionary UserValues { get; set; } = new(); /// /// Property to tell if the control is readonly, but the value is sent to the server. @@ -34,7 +39,13 @@ public abstract class ControlBase(IFormValues formValues) : ComponentBase public int MaxLength { get; set; } - internal IFormValues FormValues { get; } = formValues; + internal IHttpContextAccessor HttpContextAccessor { get; } + + internal bool HasFormValues => HttpContextAccessor.HttpContext?.Request.HasFormContentType == true; + + internal IFormCollection FormValues => HasFormValues + ? HttpContextAccessor.HttpContext!.Request.Form + : FormCollection.Empty; /// /// Value of the component. @@ -43,7 +54,7 @@ public string Text { get { - if (field == null && FormValues.ContainsFormValues()) + if (field == null && HasFormValues) { field = FormValues[Name]; } diff --git a/src/MasterData.Core/UI/Components/Controls/ControlContext.cs b/src/MasterData.Core/UI/Components/Controls/ControlContext.cs index 120be3649..3c5303326 100644 --- a/src/MasterData.Core/UI/Components/Controls/ControlContext.cs +++ b/src/MasterData.Core/UI/Components/Controls/ControlContext.cs @@ -1,5 +1,3 @@ -#nullable enable - using JJMasterData.Core.DataManager.Models; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Controls/ControlFactory.cs b/src/MasterData.Core/UI/Components/Controls/ControlFactory.cs index af4e7eb90..d9ff7d992 100644 --- a/src/MasterData.Core/UI/Components/Controls/ControlFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/ControlFactory.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Expressions; diff --git a/src/MasterData.Core/UI/Components/Controls/IFloatingLabelControl.cs b/src/MasterData.Core/UI/Components/Controls/IFloatingLabelControl.cs index a5a891c75..1f44eec29 100644 --- a/src/MasterData.Core/UI/Components/Controls/IFloatingLabelControl.cs +++ b/src/MasterData.Core/UI/Components/Controls/IFloatingLabelControl.cs @@ -1,5 +1,4 @@ -#nullable enable -namespace JJMasterData.Core.UI.Components; +namespace JJMasterData.Core.UI.Components; public interface IFloatingLabelControl { diff --git a/src/MasterData.Core/UI/Components/Controls/IconPicker/IconPickerFactory.cs b/src/MasterData.Core/UI/Components/Controls/IconPicker/IconPickerFactory.cs index 65b82fe98..86a9e6917 100644 --- a/src/MasterData.Core/UI/Components/Controls/IconPicker/IconPickerFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/IconPicker/IconPickerFactory.cs @@ -1,11 +1,10 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; -public class IconPickerFactory(IStringLocalizer stringLocalizer, IUrlHelper urlHelper, IControlFactory comboBoxFactory, IFormValues formValues) : IControlFactory +public class IconPickerFactory(IStringLocalizer stringLocalizer, IUrlHelper urlHelper, IControlFactory comboBoxFactory, IHttpContextAccessor formValues) : IControlFactory { public JJIconPicker Create() => new(stringLocalizer,urlHelper,comboBoxFactory,formValues); diff --git a/src/MasterData.Core/UI/Components/Controls/IconPicker/JJIconPicker.cs b/src/MasterData.Core/UI/Components/Controls/IconPicker/JJIconPicker.cs index 7dcd89202..03ecb69a2 100644 --- a/src/MasterData.Core/UI/Components/Controls/IconPicker/JJIconPicker.cs +++ b/src/MasterData.Core/UI/Components/Controls/IconPicker/JJIconPicker.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using JJConsulting.FontAwesome; @@ -10,7 +8,6 @@ using JJConsulting.Html.Bootstrap.Models; using JJConsulting.Html.Extensions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -19,7 +16,7 @@ public class JJIconPicker( IStringLocalizer stringLocalizer, IUrlHelper urlHelper, IControlFactory comboBoxFactory, - IFormValues formValues) : ControlBase(formValues) + IHttpContextAccessor formValues) : ControlBase(formValues) { public FontAwesomeIcon? SelectedIcon { get; set; } public string? Id { get; set; } @@ -43,6 +40,7 @@ protected internal override async ValueTask GetHtmlBuilderAsync() comboBox.Name = Name; comboBox.Id = id; comboBox.Enabled = Enabled; + comboBox.CssClass = "jj-icon-select"; if(SelectedIcon is not null) { comboBox.SelectedValue = ((int)SelectedIcon).ToString(); @@ -55,11 +53,7 @@ protected internal override async ValueTask GetHtmlBuilderAsync() ShowIcon = Enabled, }; - comboBox.Attributes["data-live-search"] = "true"; - comboBox.Attributes["data-virtual-scroll"] = "true"; - comboBox.Attributes["data-size"] = "false"; - comboBox.Attributes["data-sanitize"] = "false"; - comboBox.Attributes["data-none-results-text"] = stringLocalizer["No icons found."]; + comboBox.Attributes["data-no-results-text"] = stringLocalizer["No icons found."]; var div = new HtmlBuilder(HtmlTag.Div); div.WithCssClassIf(Enabled,"input-group"); div.Append(await comboBox.GetHtmlBuilderAsync()); @@ -75,4 +69,4 @@ protected internal override async ValueTask GetHtmlBuilderAsync() }); return div; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Controls/Lookup/JJLookup.cs b/src/MasterData.Core/UI/Components/Controls/Lookup/JJLookup.cs index b406ba014..72fdb76d2 100644 --- a/src/MasterData.Core/UI/Components/Controls/Lookup/JJLookup.cs +++ b/src/MasterData.Core/UI/Components/Controls/Lookup/JJLookup.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html; @@ -10,13 +9,8 @@ using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; - using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; @@ -25,7 +19,7 @@ namespace JJMasterData.Core.UI.Components; /// Represents a field with a value from another FormElement accessed via modal. public class JJLookup : ControlBase { - private IHttpRequest HttpRequest { get; } + private IHttpContextAccessor HttpRequest { get; } private RouteContextFactory RouteContextFactory { get; } private FormValuesService FormValuesService { get; } private IEncryptionService EncryptionService { get; } @@ -66,7 +60,7 @@ public string ModalTitle { get { - if (AutoReloadFormFields && _text is not null && FormValues.ContainsFormValues()) + if (AutoReloadFormFields && _text is not null && HasFormValues) { _text = FormValues[Name]; } @@ -109,13 +103,13 @@ internal JJLookup( FormElement formElement, FormElementField field, ControlContext controlContext, - IHttpRequest httpRequest, + IHttpContextAccessor httpRequest, RouteContextFactory routeContextFactory, FormValuesService formValuesService, IEncryptionService encryptionService, LookupService lookupService, IStringLocalizer stringLocalizer, - IComponentFactory componentFactory) : base(httpRequest.Form) + IComponentFactory componentFactory) : base(httpRequest) { RouteContext = routeContextFactory.Create(); ElementMap = field.DataItem?.ElementMap ?? new DataElementMap @@ -160,7 +154,7 @@ internal JJLookup( protected override async ValueTask BuildResultAsync() { - if (ComponentContext is ComponentContext.LookupDescription && HttpRequest.QueryString["fieldName"] == FieldName) + if (ComponentContext is ComponentContext.LookupDescription && HttpRequest.HttpContext?.Request.Query["fieldName"].ToString() == FieldName) { return await GetLookupDescription(); } @@ -236,7 +230,7 @@ protected internal override async ValueTask GetHtmlBuilderAsync() descriptionTextBox.CssClass = $"form-control jj-lookup {CssClass}"; descriptionTextBox.InputType = InputType.Text; descriptionTextBox.MaxLength = MaxLength; - descriptionTextBox.Text = description; + descriptionTextBox.Text = description ?? string.Empty; descriptionTextBox.Attributes = new Dictionary(Attributes); descriptionTextBox.Tooltip = Tooltip; descriptionTextBox.Enabled = false; @@ -293,4 +287,4 @@ false when string.IsNullOrEmpty(description) || hasDescription => " jj-icon-warn _ => (6, 6) }; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Controls/Lookup/LookupFactory.cs b/src/MasterData.Core/UI/Components/Controls/Lookup/LookupFactory.cs index 8c5754d51..9511c676d 100644 --- a/src/MasterData.Core/UI/Components/Controls/Lookup/LookupFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/Lookup/LookupFactory.cs @@ -1,14 +1,13 @@ using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; internal sealed class LookupFactory( - IHttpRequest httpRequest, + IHttpContextAccessor httpRequest, FormValuesService formValuesService, LookupService lookupService, IComponentFactory componentFactory, diff --git a/src/MasterData.Core/UI/Components/Controls/Lookup/LookupParameters.cs b/src/MasterData.Core/UI/Components/Controls/Lookup/LookupParameters.cs index 7bab1e066..fbf148956 100644 --- a/src/MasterData.Core/UI/Components/Controls/Lookup/LookupParameters.cs +++ b/src/MasterData.Core/UI/Components/Controls/Lookup/LookupParameters.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using System.Collections.Generic; using System.Text; diff --git a/src/MasterData.Core/UI/Components/Controls/Lookup/LookupResultDto.cs b/src/MasterData.Core/UI/Components/Controls/Lookup/LookupResultDto.cs index 4718dd86b..a074c421e 100644 --- a/src/MasterData.Core/UI/Components/Controls/Lookup/LookupResultDto.cs +++ b/src/MasterData.Core/UI/Components/Controls/Lookup/LookupResultDto.cs @@ -1,6 +1,3 @@ -#nullable enable - - using System.Text.Json.Serialization; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Controls/Phone/JJPhoneGroup.cs b/src/MasterData.Core/UI/Components/Controls/Phone/JJPhoneGroup.cs index 32b988d89..007b1a43d 100644 --- a/src/MasterData.Core/UI/Components/Controls/Phone/JJPhoneGroup.cs +++ b/src/MasterData.Core/UI/Components/Controls/Phone/JJPhoneGroup.cs @@ -1,14 +1,14 @@ -using System; +#nullable disable warnings +using System; using System.Linq; using JJConsulting.Html; using JJConsulting.Html.Extensions; +using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataDictionary.Services; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components.Phone; -public sealed class JJPhoneGroup(IFormValues formValues) : JJTextBox(formValues) +public sealed class JJPhoneGroup(IHttpContextAccessor formValues) : JJTextBox(formValues) { public string GroupCssClass { get; set; } @@ -21,14 +21,24 @@ public override HtmlBuilder GetHtmlBuilder() ?? (CountryHelper.TryGet(defaultCountry, out var configuredCountry) ? configuredCountry : null); var phoneValue = Text ?? string.Empty; var localPhoneValue = GetLocalPhoneValue(phoneValue, selectedCountry); + var phoneGroup = new HtmlBuilder(HtmlTag.Div) + .WithCssClass("jj-phone-group"); + + var hiddenInput = new HtmlBuilder(HtmlTag.Input) + .WithAttribute("type", "hidden") + .WithName(Name) + .WithId($"{Name}_hidden") + .WithValue(phoneValue) + .WithCssClass("jj-phone-hidden-input"); + var dropDownGroup = new HtmlBuilder(HtmlTag.Div) .WithCssClass("input-group jjform-action ") .WithCssClass(GroupCssClass) .AppendSelect(select => { - select.WithCssClass("selectpicker w-auto jj-phone-select"); - select.WithAttribute("data-live-search", "true"); - select.WithAttribute("data-style-base", "form-select form-dropdown"); + select.WithCssClass("form-select tom-select w-auto jj-phone-select"); + select.WithCssClassIf(!Enabled, "disabled"); + select.WithAttributeIf(!Enabled, "disabled"); foreach (var countryInfo in CountryHelper.All) { select.AppendOption(opt => @@ -37,26 +47,21 @@ public override HtmlBuilder GetHtmlBuilder() opt.WithAttribute("dial-code", countryInfo.DialCode); opt.WithValue(countryInfo.Code); opt.WithAttribute("data-content", GetOptionContent(countryInfo).ToString()); + opt.AppendText($"{countryInfo.Name} {countryInfo.DialCode}"); }); } }); - dropDownGroup.Append(HtmlTag.Input, hidden => - { - hidden.WithAttribute("type", "hidden"); - hidden.WithName(Name); - hidden.WithId($"{Name}_hidden"); - hidden.WithValue(phoneValue); - hidden.WithCssClass("jj-phone-hidden-input"); - }); - input.WithCssClass("jj-phone-input"); input.WithAttribute("id", Name); input.WithAttribute("name", $"{Name}_display"); input.WithAttribute("value", localPhoneValue); dropDownGroup.Append(input); - return dropDownGroup; + phoneGroup.Append(hiddenInput); + phoneGroup.Append(dropDownGroup); + + return phoneGroup; } private static CountryInfo GetCountryFromPhoneValue(string phoneValue) diff --git a/src/MasterData.Core/UI/Components/Controls/Phone/PhoneGroupFactory.cs b/src/MasterData.Core/UI/Components/Controls/Phone/PhoneGroupFactory.cs index bb90e3246..8fd07379f 100644 --- a/src/MasterData.Core/UI/Components/Controls/Phone/PhoneGroupFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/Phone/PhoneGroupFactory.cs @@ -1,10 +1,9 @@ using System; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components.Phone; -internal sealed class PhoneGroupFactory(IFormValues formValues) +internal sealed class PhoneGroupFactory(IHttpContextAccessor formValues) : IControlFactory { public JJPhoneGroup Create() diff --git a/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButton.cs b/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButton.cs index a3d805038..737d16ab7 100644 --- a/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButton.cs +++ b/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButton.cs @@ -1,14 +1,13 @@ -using System.Threading.Tasks; +#nullable disable warnings +using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -internal sealed class JJRadioButton(IFormValues formValues) : ControlBase(formValues) +internal sealed class JJRadioButton(IHttpContextAccessor formValues) : ControlBase(formValues) { public string Id { get; set; } public HtmlBuilder LabelHtml { get; } = new(); diff --git a/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButtonGroup.cs b/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButtonGroup.cs index 65bacf225..8eb5c55eb 100644 --- a/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButtonGroup.cs +++ b/src/MasterData.Core/UI/Components/Controls/RadioButton/JJRadioButtonGroup.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html; @@ -8,20 +7,19 @@ using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; public class JJRadioButtonGroup( DataItemService dataItemService, - IFormValues formValues) : ControlBase(formValues), IDataItemControl + IHttpContextAccessor formValues) : ControlBase(formValues), IDataItemControl { public string? SelectedValue { get { - if (field == null && FormValues.ContainsFormValues()) + if (field == null && HasFormValues) { field = FormValues[Name]; } @@ -57,7 +55,7 @@ public Task> GetValuesAsync() private void AppendRadioButton(HtmlBuilder html, DataItemValue item) { - var radio = new JJRadioButton(FormValues) + var radio = new JJRadioButton(HttpContextAccessor) { Id = item.Id, Name = Name, @@ -70,11 +68,11 @@ private void AppendRadioButton(HtmlBuilder html, DataItemValue item) if (DataItem.ShowIcon) { - radio.LabelHtml.Append(new JJIcon(item.Icon, item.IconColor).GetHtmlBuilder()); + radio.LabelHtml.Append(new JJIcon(item.Icon.GetValueOrDefault(), item.IconColor ?? string.Empty).GetHtmlBuilder()); } radio.LabelHtml.AppendText(item.Description!); html.Append(radio.GetHtmlBuilder()); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Controls/RadioButton/RadioButtonGroupFactory.cs b/src/MasterData.Core/UI/Components/Controls/RadioButton/RadioButtonGroupFactory.cs index 3a264430f..d06ce5fd1 100644 --- a/src/MasterData.Core/UI/Components/Controls/RadioButton/RadioButtonGroupFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/RadioButton/RadioButtonGroupFactory.cs @@ -1,10 +1,10 @@ -using JJMasterData.Core.DataDictionary.Models; +#nullable disable warnings +using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -internal sealed class RadioButtonGroupFactory(DataItemService dataItemService, IFormValues formValues) : IControlFactory +internal sealed class RadioButtonGroupFactory(DataItemService dataItemService, IHttpContextAccessor formValues) : IControlFactory { public JJRadioButtonGroup Create() { diff --git a/src/MasterData.Core/UI/Components/Controls/SearchBox/JJSearchBox.cs b/src/MasterData.Core/UI/Components/Controls/SearchBox/JJSearchBox.cs index a83d136bd..e1a70fc8a 100644 --- a/src/MasterData.Core/UI/Components/Controls/SearchBox/JJSearchBox.cs +++ b/src/MasterData.Core/UI/Components/Controls/SearchBox/JJSearchBox.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -14,8 +12,6 @@ using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; using JJMasterData.Core.Events.Args; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; @@ -84,9 +80,9 @@ public string HtmlId { get { - if (AutoReloadFormFields && _text == null && Request.Form.ContainsFormValues()) + if (AutoReloadFormFields && _text == null && Request.HttpContext!.Request.HasFormContentType) { - _text = Request.Form[$"{Name}_text"]; + _text = Request.HttpContext.Request.GetFormValue($"{Name}_text"); } return _text; @@ -161,9 +157,9 @@ public bool ScrollBar return _selectedValue; } - if (AutoReloadFormFields && Request.Form.ContainsFormValues()) + if (AutoReloadFormFields && Request.HttpContext!.Request.HasFormContentType) { - _selectedValue = Request.Form[Name]; + _selectedValue = Request.HttpContext.Request.GetFormValue(Name); } if (!string.IsNullOrEmpty(Text)) @@ -185,7 +181,7 @@ public bool ScrollBar /// public bool AutoReloadFormFields { get; set; } - private IHttpRequest Request { get; } + private IHttpContextAccessor Request { get; } private IEncryptionService EncryptionService { get; } private DataItemService DataItemService { get; } private IStringLocalizer StringLocalizer { get; } @@ -196,11 +192,6 @@ public bool ScrollBar public string SelectedValue { -#if NETFRAMEWORK - [Obsolete("Please use GetSelectedValueAsync()")] - get => JJMasterData.Core.Tasks.AsyncHelper.RunSync(GetSelectedValueAsync) ?? string.Empty; -#endif - set => _selectedValue = value; } @@ -213,7 +204,7 @@ protected RouteContext RouteContext if (_routeContext != null) return _routeContext; - var factory = new RouteContextFactory(Request.QueryString, EncryptionService); + var factory = new RouteContextFactory(Request, EncryptionService); _routeContext = factory.Create(); return _routeContext; @@ -227,10 +218,10 @@ protected RouteContext RouteContext #region "Constructors" public JJSearchBox( - IHttpRequest request, + IHttpContextAccessor request, IEncryptionService encryptionService, DataItemService dataItemService, - IStringLocalizer stringLocalizer) : base(request.Form) + IStringLocalizer stringLocalizer) : base(request) { HtmlId = Name; Request = request; @@ -251,7 +242,7 @@ public JJSearchBox( protected override async ValueTask BuildResultAsync() { - var fieldName = Request.QueryString["fieldName"]; + var fieldName = Request.HttpContext?.Request.Query["fieldName"].ToString(); if (ComponentContext is ComponentContext.SearchBox or ComponentContext.SearchBoxFilter && FieldName == fieldName) { @@ -417,14 +408,18 @@ private async Task> GetValuesAsync(string? searchId, string? private async Task> GetSearchBoxItemsAsync() { - var searchText = Request.QueryString["q"] ?? Request.Form[Name + "_text"]; + var searchText = Request.HttpContext?.Request.Query["q"].ToString(); + if (string.IsNullOrEmpty(searchText) && Request.HttpContext!.Request.HasFormContentType) + { + searchText = Request.HttpContext.Request.GetFormValue(Name + "_text"); + } var values = await GetValuesAsync(searchId: null, searchText); return values.ConvertAll(v=>new DataItemResult { Id = v.Id, Description = v.Description, IconCssClass = DataItem.ShowIcon - ? v.Icon.CssClass + ? v.Icon?.CssClass : null, IconColor = DataItem.ShowIcon ? v.IconColor diff --git a/src/MasterData.Core/UI/Components/Controls/SearchBox/SearchBoxFactory.cs b/src/MasterData.Core/UI/Components/Controls/SearchBox/SearchBoxFactory.cs index 524a2c352..ef2dd7b5d 100644 --- a/src/MasterData.Core/UI/Components/Controls/SearchBox/SearchBoxFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/SearchBox/SearchBoxFactory.cs @@ -1,17 +1,14 @@ -#nullable enable using System; using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Commons.Resources; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; internal sealed class SearchBoxFactory( DataItemService dataItemService, - IHttpRequest httpRequest, + IHttpContextAccessor httpRequest, IEncryptionService encryptionService, IStringLocalizer stringLocalizer) : IControlFactory diff --git a/src/MasterData.Core/UI/Components/Controls/Slider/JJSlider.cs b/src/MasterData.Core/UI/Components/Controls/Slider/JJSlider.cs index 4dacd2838..023c5da72 100644 --- a/src/MasterData.Core/UI/Components/Controls/Slider/JJSlider.cs +++ b/src/MasterData.Core/UI/Components/Controls/Slider/JJSlider.cs @@ -1,15 +1,13 @@ +#nullable disable warnings using System.Globalization; using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -public class JJSlider(IFormValues formValues, IControlFactory textBoxFactory) +public class JJSlider(IHttpContextAccessor formValues, IControlFactory textBoxFactory) : ControlBase(formValues) { private IControlFactory TextBoxFactory { get; } = textBoxFactory; diff --git a/src/MasterData.Core/UI/Components/Controls/Slider/SliderFactory.cs b/src/MasterData.Core/UI/Components/Controls/Slider/SliderFactory.cs index 3ba818610..d2c1d75b5 100644 --- a/src/MasterData.Core/UI/Components/Controls/Slider/SliderFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/Slider/SliderFactory.cs @@ -1,10 +1,10 @@ +#nullable disable warnings using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; internal sealed class SliderFactory( - IFormValues formValues, + IHttpContextAccessor formValues, IControlFactory textBoxFactory) : IControlFactory { diff --git a/src/MasterData.Core/UI/Components/Controls/TextArea/JJTextArea.cs b/src/MasterData.Core/UI/Components/Controls/TextArea/JJTextArea.cs index 448f32c15..5614c6918 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextArea/JJTextArea.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextArea/JJTextArea.cs @@ -1,11 +1,8 @@ -using System.Threading.Tasks; +#nullable disable warnings +using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; - using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -19,7 +16,7 @@ public class JJTextArea : ControlBase, IFloatingLabelControl private IStringLocalizer StringLocalizer { get; } public int Rows { get; set; } - public JJTextArea(IFormValues formValues,IStringLocalizer stringLocalizer) : base(formValues) + public JJTextArea(IHttpContextAccessor formValues,IStringLocalizer stringLocalizer) : base(formValues) { StringLocalizer = stringLocalizer; Attributes.Add("class", "form-control"); diff --git a/src/MasterData.Core/UI/Components/Controls/TextArea/TextAreaFactory.cs b/src/MasterData.Core/UI/Components/Controls/TextArea/TextAreaFactory.cs index 920f9ce6e..e5605c376 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextArea/TextAreaFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextArea/TextAreaFactory.cs @@ -1,12 +1,12 @@ +#nullable disable warnings using System; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; internal sealed class TextAreaFactory( - IFormValues formValues, + IHttpContextAccessor formValues, IStringLocalizer stringLocalizer) : IControlFactory { diff --git a/src/MasterData.Core/UI/Components/Controls/TextBox/InputAddons.cs b/src/MasterData.Core/UI/Components/Controls/TextBox/InputAddons.cs index 30a0eea6c..22506e97d 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextBox/InputAddons.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextBox/InputAddons.cs @@ -1,4 +1,5 @@ -using JJConsulting.Html.Bootstrap.Components; +#nullable disable warnings +using JJConsulting.Html.Bootstrap.Components; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextBox.cs b/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextBox.cs index 576004454..1fa39c047 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextBox.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextBox.cs @@ -4,8 +4,6 @@ using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; @@ -41,7 +39,7 @@ public double? MaxValue set => SetAttribute(FormElementField.MaxValueAttribute, value.ToString()); } - public JJTextBox(IFormValues formValues) : base(formValues) + public JJTextBox(IHttpContextAccessor formValues) : base(formValues) { InputType = InputType.Text; Visible = true; diff --git a/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextGroup.cs b/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextGroup.cs index 50a7d94ac..89c633078 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextGroup.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextBox/JJTextGroup.cs @@ -1,17 +1,15 @@ +#nullable disable warnings using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; -using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -public sealed class JJTextGroup(IFormValues formValues) +public sealed class JJTextGroup(IHttpContextAccessor formValues) : JJTextBox(formValues), IFloatingLabelControl { public string FloatingLabel { get; set; } diff --git a/src/MasterData.Core/UI/Components/Controls/TextBox/TextBoxFactory.cs b/src/MasterData.Core/UI/Components/Controls/TextBox/TextBoxFactory.cs index d5a7fe9c8..99c0959c7 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextBox/TextBoxFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextBox/TextBoxFactory.cs @@ -1,9 +1,9 @@ +#nullable disable warnings using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; -internal sealed class TextBoxFactory(IFormValues formValues) +internal sealed class TextBoxFactory(IHttpContextAccessor formValues) : IControlFactory { public JJTextBox Create() diff --git a/src/MasterData.Core/UI/Components/Controls/TextBox/TextGroupFactory.cs b/src/MasterData.Core/UI/Components/Controls/TextBox/TextGroupFactory.cs index 6d8413ff3..3739803ba 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextBox/TextGroupFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextBox/TextGroupFactory.cs @@ -5,14 +5,13 @@ using JJConsulting.Html.Bootstrap.Components; using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; using static JJMasterData.Core.UI.DateFormatMapper; namespace JJMasterData.Core.UI.Components; public sealed class TextGroupFactory( - IFormValues formValues, + IHttpContextAccessor formValues, IStringLocalizer stringLocalizer, ActionButtonFactory actionButtonFactory) : IControlFactory @@ -244,7 +243,9 @@ private void SetDefaultAttributes(JJTextGroup textGroup, FormElementField field, textGroup.InputType = InputType.Text; if (pageState == PageState.Filter && isMultiFilter) { - textGroup.Attributes.Add("data-role", "tagsinput"); + cssClassList.Add("tom-select"); + cssClassList.Add("tom-select-tags"); + textGroup.Attributes.Add("data-tom-select-tags", "true"); textGroup.MaxLength = 0; } break; diff --git a/src/MasterData.Core/UI/Components/Controls/TextFile/JJTextFile.cs b/src/MasterData.Core/UI/Components/Controls/TextFile/JJTextFile.cs index d5090cdcd..e486009a2 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextFile/JJTextFile.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextFile/JJTextFile.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using System.Linq; +#nullable disable warnings +using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.FontAwesome; using JJConsulting.Html; @@ -7,20 +7,19 @@ using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Security.Cryptography.Abstractions; +using JJMasterData.Commons.Storage; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.DataManager.IO; -using JJMasterData.Core.Http.Abstractions; - using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; -public sealed class JJTextFile(IHttpRequest request, - IComponentFactory componentFactory, - IStringLocalizer stringLocalizer, - IEncryptionService encryptionService) - : ControlBase(request.Form) +public sealed class JJTextFile( + IHttpContextAccessor request, + IComponentFactory componentFactory, + IStringLocalizer stringLocalizer, + IEncryptionService encryptionService) + : ControlBase(request) { internal IEncryptionService EncryptionService { get; } = encryptionService; internal IStringLocalizer StringLocalizer { get; } = stringLocalizer; @@ -38,7 +37,6 @@ public Dictionary FormStateValues public override string Tooltip { - get => FormElementField.HelpDescription; set => FormElementField.HelpDescription = value; } @@ -49,8 +47,6 @@ public override string Tooltip public FormElement FormElement { get; set; } - private FormFilePathBuilder PathBuilder => field ??= new FormFilePathBuilder(FormElement); - private RouteContext RouteContext { get @@ -58,9 +54,9 @@ private RouteContext RouteContext if (field != null) return field; - var factory = new RouteContextFactory(request.QueryString, EncryptionService); + var factory = new RouteContextFactory(request, EncryptionService); field = factory.Create(); - + return field; } } @@ -69,35 +65,13 @@ public JJUploadView UploadView { get { - if (field is not null) + if (field is not null) return field; - - field = componentFactory.UploadView.Create(); - field.Name = $"{FormElementField.Name}-upload-view"; + + field = componentFactory.UploadView.Create(FormElement, FormElementField, FormStateValues); field.ParentName = FormElement.ParentName ?? ParentName; - field.Title = string.Empty; - field.AutoSave = false; field.JsCallback = Scripts.GetRefreshScript(); - field.RenameAction.SetVisible(true); - - if (HasPk()) - field.FolderPath = GetFolderPath(); - - var dataFile = FormElementField.DataFile!; - field.UploadArea.Multiple = dataFile.MultipleFile; - field.UploadArea.MaxFileSize = dataFile.MaxFileSize; - field.UploadArea.ShowFileSize = dataFile.ExportAsLink; - field.UploadArea.AllowedTypes = dataFile.AllowedTypes; - field.UploadArea.EnableCopyPaste = dataFile.AllowPasting; - field.UploadArea.RouteContext.ElementName = FormElement.Name; - field.UploadArea.RouteContext.ParentElementName = FormElement.ParentName; - field.UploadArea.RouteContext.ComponentContext = ComponentContext.TextFileFileUpload; - field.UploadArea.QueryStringParams["fieldName"] = FieldName; - field.ViewGallery = dataFile.ViewGallery; - - if (dataFile.ShowAsUploadView) - field.GridView.EmptyDataText = null; - + if (!Enabled || PageState is PageState.View) field.Disable(); @@ -127,15 +101,8 @@ protected override async ValueTask BuildResultAsync() protected internal override async ValueTask GetHtmlBuilderAsync() { - if (FormElementField.DataFile!.ShowAsUploadView) - { - var uploadViewHtml = ((RenderedComponentResult)await GetUploadViewResultAsync()).HtmlBuilder; - uploadViewHtml.Append(GetHiddenInputHtml()); - return uploadViewHtml; - } - if (!Enabled) - UploadView.ClearMemoryFiles(); + await UploadView.ClearTemporaryFilesAsync(); var textGroup = componentFactory.Controls.TextGroup.Create(); textGroup.CssClass = CssClass; @@ -143,7 +110,7 @@ protected internal override async ValueTask GetHtmlBuilderAsync() textGroup.ReadOnly = true; textGroup.Tooltip = Tooltip; textGroup.Attributes = Attributes; - textGroup.Text = GetPresentationText(); + textGroup.Text = await GetPresentationTextAsync(); var button = new JJLinkButton { @@ -157,83 +124,69 @@ protected internal override async ValueTask GetHtmlBuilderAsync() var html = new HtmlBuilder(); html.Append(await textGroup.GetHtmlBuilderAsync()); - html.Append(GetHiddenInputHtml()); + html.Append(await GetHiddenInputsHtmlAsync()); + html.Append(UploadView.GetHiddenInputsHtmlAsync()); return html; } private async Task GetUploadViewResultAsync() { - var result = await UploadView.GetUploadViewResult(); + var result = await UploadView.GetUploadViewResult(appendHiddenInputs: false); if (result is not RenderedComponentResult uploadViewResult) return result; var html = new HtmlBuilder(); html.Append(uploadViewResult.HtmlBuilder); - html.AppendScript(Scripts.GetRefreshInputsScript()); + html.AppendScript(await Scripts.GetRefreshInputsScriptAsync()); return new RenderedComponentResult(html); } - private HtmlBuilder GetHiddenInputHtml() + private async Task GetHiddenInputsHtmlAsync() { - var input = new HtmlBuilder(HtmlTag.Input); - input.WithAttribute("type", "hidden") + var fileName = await GetFileNameAsync(); + var html = new HtmlBuilder(); + var fileInput = new HtmlBuilder(HtmlTag.Input); + fileInput.WithAttribute("type", "hidden") .WithNameAndId(Name) - .WithAttribute("value", GetFileName()); - return input; - } + .WithAttribute("value", fileName); + html.Append(fileInput); - public void SaveMemoryFiles() - { - string folderPath = GetFolderPath(); - var uploadView = UploadView; - uploadView.SaveMemoryFiles(folderPath); + return html; } - public void DeleteAll() + public string GetFolderPath() { - var uploadView = UploadView; - uploadView.FolderPath = GetFolderPath(); - uploadView.DeleteAll(); + return FileStoragePath.GetFolderPath(FormElement, FormElementField, FormStateValues); } - private bool HasPk() - { - var pkFields = FormElement.Fields.FindAll(x => x.IsPk); - if (pkFields.Count == 0) - return false; - return pkFields.All(pkField => FormStateValues.ContainsKey(pkField.Name) && !string.IsNullOrEmpty(FormStateValues[pkField.Name]?.ToString())); - } + internal string GetDraftInputName() => $"{FormElementField.Name}-upload-view-files-draft-id"; - public string GetFolderPath() + internal async Task GetFileNameAsync() { - return PathBuilder.GetFolderPath(FormElementField, FormStateValues); - } + var fileNames = string.Empty; + var files = await UploadView.GetFilesAsync(); - internal string GetFileName() - { - string fileNames = string.Empty; - var listFile = UploadView.GetFiles().FindAll(x => !x.Deleted); - foreach (var file in listFile) + foreach (var file in files) { if (fileNames != string.Empty) fileNames += ","; - fileNames += file.Content.FileName; + fileNames += file.FileName; } return fileNames; } - internal string GetPresentationText() + internal async Task GetPresentationTextAsync() { - var files = UploadView.GetFiles().FindAll(x => !x.Deleted); + var files = await UploadView.GetFilesAsync(); return files.Count switch { 0 => string.Empty, - 1 => files[0].Content.FileName, + 1 => files[0].FileName, _ => StringLocalizer["{0} Selected Files", files.Count] }; } @@ -243,48 +196,54 @@ internal HtmlBuilder GetButtonGroupHtml() if (string.IsNullOrEmpty(Text)) return new HtmlBuilder(string.Empty); - string[] files = Text.Split(','); + var files = Text.Split(','); if (files.Length == 1) - { - var btn = GetLinkButton(files[0]); - return btn.GetHtmlBuilder(); - } + return GetLinkButton(files[0]).GetHtmlBuilder(); var caretHtml = new HtmlBuilder(); caretHtml.AppendComponent(new JJIcon(FontAwesomeIcon.CloudDownload)).WithCssClass("me-1"); caretHtml.AppendText($"{files.Length} {StringLocalizer["Files"]}"); + var btnGroup = new JJLinkButtonGroup { CaretHtml = caretHtml }; - btnGroup.Attributes.Add("onclick","event.stopPropagation()"); - - foreach (var filename in files) + btnGroup.Attributes.Add("onclick", "event.stopPropagation()"); + + foreach (var fileName in files) { - btnGroup.Actions.Add(GetLinkButton(filename)); + btnGroup.Actions.Add(GetLinkButton(fileName)); } return btnGroup.GetHtmlBuilder(); } - private JJLinkButton GetLinkButton(string filename) + private JJLinkButton GetLinkButton(string fileName) { - var btn = new JJLinkButton(); - btn.IconClass = "fa fa-cloud-download"; - btn.Text = filename; - btn.Attributes.Add("onclick", "event.stopPropagation()"); - btn.UrlAction = GetDownloadLink(filename); - btn.IsGroup = true; - - return btn; + return new JJLinkButton + { + IconClass = "fa fa-cloud-download", + Text = fileName, + UrlAction = GetDownloadLink(fileName), + IsGroup = true, + Attributes = + { + { "onclick", "event.stopPropagation()" } + } + }; } private string GetDownloadLink(string fileName) { - var filePath = GetFolderPath() + fileName; - var fileDownloader = componentFactory.Downloader.Create(); - fileDownloader.FilePath = filePath; + var fullPath = FileStoragePath.Combine(UploadView.FolderPath, fileName); + var fileDownloader = componentFactory.Downloader.Create(fullPath); return fileDownloader.GetDownloadUrl(); } -} \ No newline at end of file + + public Task PromoteDraftFilesAsync() => UploadView.PromoteDraftFilesAsync(); + + public Task ClearTemporaryFilesAsync() => UploadView.DeleteAllAsync(); + + public Task DeleteAllAsync() => UploadView.DeleteAllAsync(); +} diff --git a/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileFactory.cs b/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileFactory.cs index 310b5236a..38494694e 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileFactory.cs @@ -1,13 +1,13 @@ +#nullable disable warnings using System; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; internal sealed class TextFileFactory( - IHttpRequest request, + IHttpContextAccessor request, IComponentFactory componentFactory, IEncryptionService encryptionService, IStringLocalizer stringLocalizer) @@ -44,4 +44,4 @@ public JJTextFile Create(FormElement formElement, FormElementField field, Contro return textFile; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileScripts.cs b/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileScripts.cs index 58c14bd50..50ee5e186 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileScripts.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextFile/TextFileScripts.cs @@ -1,7 +1,5 @@ -#nullable enable - +using System.Threading.Tasks; using System.Web; -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Routing; namespace JJMasterData.Core.UI.Components; @@ -16,19 +14,21 @@ public string GetShowScript() var routeContext = RouteContext.FromFormElement(textFile.FormElement, ComponentContext.TextFileUploadView); - return $"TextFileHelper.showUploadView('{textFile.FieldName}','{title}','{textFile.EncryptionService.EncryptObject(routeContext)}');"; + return $"TextFileHelper.showUploadView('{textFile.FieldName}','{title}','{textFile.EncryptionService.EncryptObject(routeContext)}','{textFile.GetDraftInputName()}');"; } public string GetRefreshScript() { var routeContext = RouteContext.FromFormElement(textFile.FormElement, ComponentContext.TextFileUploadView); - return $"TextFileHelper.refresh('{textFile.FieldName}','{textFile.EncryptionService.EncryptObject(routeContext)}')"; + return $"TextFileHelper.refresh('{textFile.FieldName}','{textFile.EncryptionService.EncryptObject(routeContext)}','{textFile.GetDraftInputName()}')"; } - - public string GetRefreshInputsScript() + + public async Task GetRefreshInputsScriptAsync() { - return $"TextFileHelper.refreshInputs('{textFile.Name}','{textFile.GetPresentationText()}','{textFile.GetFileName()}')"; + var presentationText = HttpUtility.JavaScriptStringEncode(await textFile.GetPresentationTextAsync()); + var fileName = HttpUtility.JavaScriptStringEncode(await textFile.GetFileNameAsync()); + + return $"TextFileHelper.refreshInputs('{textFile.Name}','{presentationText}','{fileName}')"; } - -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Controls/TextRange/JJTextRange.cs b/src/MasterData.Core/UI/Components/Controls/TextRange/JJTextRange.cs index 6eccd5811..df812efde 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextRange/JJTextRange.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextRange/JJTextRange.cs @@ -1,17 +1,15 @@ +#nullable disable warnings using System; using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Data.Entity.Models; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; - using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components.TextRange; -public class JJTextRange(IFormValues formValues, +public class JJTextRange(IHttpContextAccessor formValues, IStringLocalizer stringLocalizer) : ControlBase(formValues) { diff --git a/src/MasterData.Core/UI/Components/Controls/TextRange/TextRangeFactory.cs b/src/MasterData.Core/UI/Components/Controls/TextRange/TextRangeFactory.cs index 2ce2592eb..77af27435 100644 --- a/src/MasterData.Core/UI/Components/Controls/TextRange/TextRangeFactory.cs +++ b/src/MasterData.Core/UI/Components/Controls/TextRange/TextRangeFactory.cs @@ -1,12 +1,12 @@ +#nullable disable warnings using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components.TextRange; internal sealed class TextRangeFactory( - IHttpContext httpContext, + IHttpContextAccessor httpContext, IStringLocalizer stringLocalizer, TextGroupFactory textGroupFactory ) @@ -14,7 +14,7 @@ TextGroupFactory textGroupFactory { public JJTextRange Create() { - return new JJTextRange(httpContext.Request.Form,stringLocalizer); + return new JJTextRange(httpContext, stringLocalizer); } public JJTextRange Create(FormElement formElement, FormElementField field, ControlContext context) @@ -40,4 +40,4 @@ public JJTextRange Create(FormElement formElement, FormElementField field, Contr return range; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/DataPanel/DataPanelExpressionScripts.cs b/src/MasterData.Core/UI/Components/DataPanel/DataPanelExpressionScripts.cs index 1e8b7ec1c..e30f00068 100644 --- a/src/MasterData.Core/UI/Components/DataPanel/DataPanelExpressionScripts.cs +++ b/src/MasterData.Core/UI/Components/DataPanel/DataPanelExpressionScripts.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Linq; using System.Text; using JJMasterData.Commons.Util; @@ -90,10 +91,6 @@ private string ExecuteExpression(string exp, List list) { val = $"'{value}'"; } - else if (dataPanel.CurrentContext.Session.HasKey(fieldName)) - { - val = $"'{dataPanel.CurrentContext.Session[fieldName]}'"; - } //Hidden fields else if (dataPanel.Values.TryGetValue(fieldName, out var panelValue)) { diff --git a/src/MasterData.Core/UI/Components/DataPanel/DataPanelFactory.cs b/src/MasterData.Core/UI/Components/DataPanel/DataPanelFactory.cs index 06251943e..51d40f03b 100644 --- a/src/MasterData.Core/UI/Components/DataPanel/DataPanelFactory.cs +++ b/src/MasterData.Core/UI/Components/DataPanel/DataPanelFactory.cs @@ -5,14 +5,13 @@ using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; internal sealed class DataPanelFactory(IEntityRepository entityRepository, IDataDictionaryRepository dataDictionaryRepository, - IHttpContext httpContext, + IHttpContextAccessor httpContext, IEncryptionService encryptionService, FieldFormattingService fieldFormattingService, FieldValidationService fieldValidationService, diff --git a/src/MasterData.Core/UI/Components/DataPanel/DataPanelForm.cs b/src/MasterData.Core/UI/Components/DataPanel/DataPanelForm.cs index 930b0b110..a980f3d98 100644 --- a/src/MasterData.Core/UI/Components/DataPanel/DataPanelForm.cs +++ b/src/MasterData.Core/UI/Components/DataPanel/DataPanelForm.cs @@ -1,5 +1,4 @@ -#nullable enable - + using System; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/MasterData.Core/UI/Components/DataPanel/DataPanelLayout.cs b/src/MasterData.Core/UI/Components/DataPanel/DataPanelLayout.cs index a9abe4e79..fd5af3989 100644 --- a/src/MasterData.Core/UI/Components/DataPanel/DataPanelLayout.cs +++ b/src/MasterData.Core/UI/Components/DataPanel/DataPanelLayout.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using JetBrains.Annotations; @@ -9,7 +10,6 @@ using JJMasterData.Commons.Security.Hashing; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Expressions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; @@ -22,7 +22,7 @@ internal sealed class DataPanelLayout(JJDataPanel dataPanel) private readonly bool _renderPanelGroup = dataPanel.RenderPanelGroup; private readonly FormElement _formElement = dataPanel.FormElement; private readonly DataPanelForm _dataPanelForm = new(dataPanel); - private readonly IFormValues _formValues = dataPanel.CurrentContext.Request.Form; + private readonly IHttpContextAccessor _formValues = dataPanel.CurrentContext; private readonly PageState _pageState = dataPanel.PageState; private readonly ExpressionsService _expressionsService= dataPanel.ExpressionsService; diff --git a/src/MasterData.Core/UI/Components/DataPanel/DataPanelScripts.cs b/src/MasterData.Core/UI/Components/DataPanel/DataPanelScripts.cs index 168af3c08..7d7b36e0f 100644 --- a/src/MasterData.Core/UI/Components/DataPanel/DataPanelScripts.cs +++ b/src/MasterData.Core/UI/Components/DataPanel/DataPanelScripts.cs @@ -1,4 +1,3 @@ -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Routing; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/DataPanel/JJDataPanel.cs b/src/MasterData.Core/UI/Components/DataPanel/JJDataPanel.cs index b6be0f7c2..7c2f1b43c 100644 --- a/src/MasterData.Core/UI/Components/DataPanel/JJDataPanel.cs +++ b/src/MasterData.Core/UI/Components/DataPanel/JJDataPanel.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -15,17 +16,8 @@ using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.Tasks; - using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; -#if NET48 -using JJMasterData.Commons.Configuration; -#endif - namespace JJMasterData.Core.UI.Components; /// @@ -33,7 +25,7 @@ namespace JJMasterData.Core.UI.Components; /// public class JJDataPanel( IEntityRepository entityRepository, - IHttpContext currentContext, + IHttpContextAccessor currentContext, IEncryptionService encryptionService, FieldFormattingService fieldFormattingService, FieldValidationService fieldValidationService, @@ -52,7 +44,7 @@ public class JJDataPanel( #endregion #region "Properties" - public Dictionary UserValues { get; set; } = new(StringComparer.InvariantCultureIgnoreCase); + public Dictionary UserValues { get; set; } = new(StringComparer.InvariantCultureIgnoreCase); /// /// Layout form settings /// @@ -75,7 +67,7 @@ public PageState PageState get { if (_pageState is null && ContainsPanelState()) - _pageState = (PageState)int.Parse(CurrentContext.Request.Form[$"data-panel-state-{Name}"]); + _pageState = (PageState)int.Parse(CurrentContext.HttpContext!.Request.GetFormValue($"data-panel-state-{Name}")); return _pageState ?? PageState.View; } @@ -86,7 +78,7 @@ public PageState PageState } } - internal bool ContainsPanelState() => CurrentContext.Request.Form[$"data-panel-state-{Name}"] != null; + internal bool ContainsPanelState() => !string.IsNullOrEmpty(CurrentContext.HttpContext!.Request.GetFormValue($"data-panel-state-{Name}")); internal bool HasCustomPanelState { get; private set; } @@ -100,20 +92,22 @@ public PageState PageState /// Field Values. /// Key=Field Name, Value=Field Value /// - public Dictionary Values { get; set; } = new(StringComparer.InvariantCultureIgnoreCase); + public Dictionary Values { get; set; } = new(StringComparer.InvariantCultureIgnoreCase); /// /// Values not intended to be edited at the client. They are encrypted using . /// - [CanBeNull] - public Dictionary SecretValues + public Dictionary? SecretValues { get { if (field == null && - CurrentContext.Request.Form.TryGetValue($"data-panel-secret-values-{Name}", out var secretValues)) + CurrentContext.HttpContext!.Request.HasFormContentType && CurrentContext.HttpContext!.Request.Form.TryGetValue($"data-panel-secret-values-{Name}", out var secretValues)) + { field = EncryptionService.DecryptDictionary(secretValues); + } + return field; } set; @@ -144,7 +138,7 @@ private RouteContext RouteContext if (field != null) return field; - var factory = new RouteContextFactory(CurrentContext.Request.QueryString, EncryptionService); + var factory = new RouteContextFactory(CurrentContext, EncryptionService); field = factory.Create(); return field; @@ -157,15 +151,15 @@ public bool IsAtModal { get { - if (CurrentContext.Request.Form[$"data-panel-is-at-modal-{Name}"] != null) - field = StringManager.ParseBool(CurrentContext.Request.Form[$"data-panel-is-at-modal-{Name}"]); + if (!string.IsNullOrEmpty(CurrentContext.HttpContext!.Request.GetFormValue($"data-panel-is-at-modal-{Name}"))) + field = StringManager.ParseBool(CurrentContext.HttpContext!.Request.GetFormValue($"data-panel-is-at-modal-{Name}")); return field; } set; } - internal IHttpContext CurrentContext { get; } = currentContext; + internal IHttpContextAccessor CurrentContext { get; } = currentContext; internal IEncryptionService EncryptionService { get; } = encryptionService; internal FieldFormattingService FieldFormattingService { get; } = fieldFormattingService; internal ExpressionsService ExpressionsService { get; } = expressionsService; @@ -179,7 +173,7 @@ public bool IsAtModal public JJDataPanel( FormElement formElement, IEntityRepository entityRepository, - IHttpContext currentContext, + IHttpContextAccessor currentContext, IEncryptionService encryptionService, FieldFormattingService fieldFormattingService, FieldValidationService fieldValidationService, @@ -225,7 +219,7 @@ protected override async Task BuildResultAsync() case ComponentContext.LookupDescription: return await GetFieldResultAsync(); case ComponentContext.DownloadFile: - return ComponentFactory.Downloader.Create().GetDownloadResult(); + return await ComponentFactory.Downloader.Create().GetDownloadResultAsync(); case ComponentContext.DataPanelReload: { var html = await GetHtmlBuilderAsync(); @@ -233,7 +227,7 @@ protected override async Task BuildResultAsync() } case ComponentContext.UrlRedirect: { - string encryptedActionMap = CurrentContext.Request.Form[$"current-action-map-{Name}"]; + string encryptedActionMap = CurrentContext.HttpContext!.Request.GetFormValue($"current-action-map-{Name}"); if (string.IsNullOrEmpty(encryptedActionMap)) return null; @@ -249,7 +243,7 @@ protected override async Task BuildResultAsync() private async ValueTask GetFieldResultAsync() where TControl : ControlBase { - var fieldName = CurrentContext.Request.QueryString["fieldName"]; + var fieldName = CurrentContext.HttpContext!.Request.Query["fieldName"]; var formStateData = new FormStateData(await GetFormValuesAsync(), UserValues, PageState); var controlContext = new ControlContext(formStateData, Name); @@ -300,7 +294,7 @@ internal void AppendHiddenInputs(HtmlBuilder html) private string GetPkHiddenInput() { var pkValues = DataHelper.ParsePkValues(FormElement, Values, '|'); - return EncryptionService.EncryptStringWithUrlEscape(pkValues); + return EncryptionService.EncryptString(pkValues); } private string GetHtmlFormScript() @@ -322,17 +316,11 @@ private string GetHtmlFormScript() script.AppendLine("});"); return script.ToString(); } - - [Obsolete("Please use GetFormValuesAsync")] - public Dictionary GetFormValues() - { - return AsyncHelper.RunSync(GetFormValuesAsync); - } - + /// /// Load form data with default values and triggers /// - public async Task> GetFormValuesAsync() + public async Task> GetFormValuesAsync() { var formStateData = new FormStateData(Values, UserValues, PageState); var mergedValues = await formValuesService.GetFormValuesWithMergedValuesAsync(FormElement, formStateData, AutoReloadFormFields, FieldNamePrefix); @@ -348,13 +336,6 @@ public async Task> GetFormValuesAsync() return Values; } -#if NETFRAMEWORK - [Obsolete("Please use LoadValuesFromPkAsync")] - public void LoadValuesFromPK(Dictionary pks) - { - Values = AsyncHelper.RunSync(()=>entityRepository.GetFieldsAsync(FormElement, pks)); - } -#endif public async Task LoadValuesFromPkAsync(Dictionary pks) { Values = await entityRepository.GetFieldsAsync(FormElement, pks); @@ -378,14 +359,18 @@ public Task LoadValuesFromPkAsync(params object[] pks) return LoadValuesFromPkAsync(filter); } - - - /// - public Dictionary ValidateFields(Dictionary values) + + + public Dictionary ValidateFields(Dictionary values) { return ValidateFields(values, PageState); } + public ValueTask> ValidateFieldsAsync(Dictionary values, bool enableErrorLink = true) + { + return fieldValidationService.ValidateFieldsAsync(FormElement, values, PageState.Delete, enableErrorLink); + } + /// /// Validate form fields and return a list with errors /// @@ -393,11 +378,11 @@ public Dictionary ValidateFields(Dictionary valu /// Key = Field Name /// Valor = Error message /// - public Dictionary ValidateFields(Dictionary values, PageState pageState, bool enableErrorLink = true) + public Dictionary ValidateFields(Dictionary values, PageState pageState, bool enableErrorLink = true) { return fieldValidationService.ValidateFields(FormElement, values, pageState, enableErrorLink); } - + internal Task GetUrlRedirectResult(ActionMap actionMap) { return urlRedirectService.GetUrlRedirectResult(this, actionMap); diff --git a/src/MasterData.Core/UI/Components/Exportation/DataExportationFactory.cs b/src/MasterData.Core/UI/Components/Exportation/DataExportationFactory.cs index e38c8f702..0e6df1fd3 100644 --- a/src/MasterData.Core/UI/Components/Exportation/DataExportationFactory.cs +++ b/src/MasterData.Core/UI/Components/Exportation/DataExportationFactory.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Commons.Tasks; using JJMasterData.Core.Configuration.Options; @@ -7,7 +8,6 @@ using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Exportation; using JJMasterData.Core.DataManager.Expressions; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -17,14 +17,16 @@ namespace JJMasterData.Core.UI.Components; internal class DataExportationFactory( IDataDictionaryRepository dataDictionaryRepository, IMasterDataUser masterDataUser, + IUrlHelper urlHelper, ExpressionsService expressionsService, IOptionsSnapshot options, IBackgroundTaskManager backgroundTaskManager, - IHttpContext httpContext, + IHttpContextAccessor httpContext, IStringLocalizer stringLocalizer, ILoggerFactory loggerFactory, IComponentFactory componentFactory, IEncryptionService encryptionService, + IFileStorage fileStorage, DataExportationWriterFactory dataExportationWriterFactory ) : IFormElementComponentFactory { @@ -39,6 +41,7 @@ public JJDataExportation Create(FormElement formElement) return new JJDataExportation( formElement, masterDataUser, + urlHelper, expressionsService, options, backgroundTaskManager, @@ -47,6 +50,7 @@ public JJDataExportation Create(FormElement formElement) loggerFactory, httpContext, encryptionService, + fileStorage, dataExportationWriterFactory); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Exportation/DataExportationLog.cs b/src/MasterData.Core/UI/Components/Exportation/DataExportationLog.cs index 9121957cf..2c51b0ed2 100644 --- a/src/MasterData.Core/UI/Components/Exportation/DataExportationLog.cs +++ b/src/MasterData.Core/UI/Components/Exportation/DataExportationLog.cs @@ -3,8 +3,6 @@ using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; using JJMasterData.Core.DataManager.Exportation; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Exportation/DataExportationScripts.cs b/src/MasterData.Core/UI/Components/Exportation/DataExportationScripts.cs index 7cfda12bc..51bef9a2e 100644 --- a/src/MasterData.Core/UI/Components/Exportation/DataExportationScripts.cs +++ b/src/MasterData.Core/UI/Components/Exportation/DataExportationScripts.cs @@ -1,6 +1,5 @@ using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Routing; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Exportation/DataExportationSettings.cs b/src/MasterData.Core/UI/Components/Exportation/DataExportationSettings.cs index 2b2cffb36..2af9b25b5 100644 --- a/src/MasterData.Core/UI/Components/Exportation/DataExportationSettings.cs +++ b/src/MasterData.Core/UI/Components/Exportation/DataExportationSettings.cs @@ -1,18 +1,18 @@ +#nullable disable warnings + using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using JJConsulting.FontAwesome; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Bootstrap.Models; using JJConsulting.Html.Extensions; -using JJMasterData.Commons.Util; -using JJMasterData.Core.DataDictionary; -using JJMasterData.Core.DataDictionary.Models; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Core.DataManager.Exportation; using JJMasterData.Core.DataManager.Exportation.Configuration; -using JJMasterData.Core.Html; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -21,14 +21,14 @@ internal sealed class DataExportationSettings(JJDataExportation dataExportation) { private readonly IStringLocalizer _stringLocalizer = dataExportation.StringLocalizer; - internal HtmlBuilder GetHtmlBuilder() + internal async Task GetHtmlBuilderAsync() { var html = new HtmlBuilder(HtmlTag.Div); - var folderPath = DataExportationHelper.GetFolderPath(dataExportation); + var folderPath = DataExportationHelper.GetExportationFolderPath(dataExportation); html.WithCssClass("container-fluid"); - html.Append(GetFormHtmlElement(folderPath)); + html.Append(await GetFormHtmlElementAsync(folderPath)); html.AppendHr(); html.AppendDiv(div => { @@ -64,7 +64,7 @@ internal HtmlBuilder GetHtmlBuilder() return html; } - private HtmlBuilder GetFormHtmlElement(string exportationFolderPath) + private async Task GetFormHtmlElementAsync(string exportationFolderPath) { var div = new HtmlBuilder(HtmlTag.Div); div.WithCssClass("row"); @@ -79,7 +79,7 @@ private HtmlBuilder GetFormHtmlElement(string exportationFolderPath) div.Append(GetFirstLineField()); - div.Append(GetFilesCollapsePanelHtmlBuilder(exportationFolderPath)); + div.Append(await GetFilesCollapsePanelHtmlBuilderAsync(exportationFolderPath)); div.Append(HtmlTag.Div, div => { @@ -281,9 +281,9 @@ private JJAlert GetTooManyRecordsAlert(string name) return alert; } - private HtmlBuilder GetFilesCollapsePanelHtmlBuilder(string exportationFolderPath) + private async Task GetFilesCollapsePanelHtmlBuilderAsync(string exportationFolderPath) { - var files = GetGeneratedFiles(exportationFolderPath); + var files = await GetGeneratedFilesAsync(exportationFolderPath); var filesCount = files.Count; var panel = new JJCollapsePanel { @@ -298,7 +298,7 @@ private HtmlBuilder GetFilesCollapsePanelHtmlBuilder(string exportationFolderPat return panel.GetHtmlBuilder()?.WithCssClass($"col-sm-12 {BootstrapHelper.FormGroup}"); } - private HtmlBuilder GetLastFilesHtml(List files) + private HtmlBuilder GetLastFilesHtml(List files) { if (files == null || files.Count == 0) return new HtmlBuilder(_stringLocalizer["No recently generated files."]); @@ -306,11 +306,8 @@ private HtmlBuilder GetLastFilesHtml(List files) var html = new HtmlBuilder(HtmlTag.Div); foreach (var file in files) { - if (FileIO.IsFileLocked(file)) - continue; - - var icon = JJDataExportation.GetFileIcon(file.Extension); - string url = dataExportation.GetDownloadUrl(file.FullName); + var icon = JJDataExportation.GetFileIcon(Path.GetExtension(file.FileName)); + string url = dataExportation.GetDownloadUrl(file.FileName); var div = new HtmlBuilder(HtmlTag.Div); div.WithCssClass("mb-1"); @@ -320,7 +317,7 @@ private HtmlBuilder GetLastFilesHtml(List files) { a.WithAttribute("href", url); a.WithAttribute("title", "Download"); - a.AppendText(file.Name); + a.AppendText(file.FileName); }); html.Append(div); @@ -329,17 +326,12 @@ private HtmlBuilder GetLastFilesHtml(List files) return html; } - private static List GetGeneratedFiles(string exportationFolderPath) + private async Task> GetGeneratedFilesAsync(string exportationFolderPath) { - var list = new List(); - - var oDir = new DirectoryInfo(exportationFolderPath); - - if (oDir.Exists) - list.AddRange(oDir.GetFiles("*", SearchOption.AllDirectories)); - - return list.OrderByDescending(f => f.CreationTime).ToList(); + return (await dataExportation.FileStorage.ListAsync(exportationFolderPath)) + .OrderByDescending(f => f.LastWriteTime) + .ToList(); } private bool PdfWriterExists() => dataExportation.DataExportationWriterFactory.PdfWriterExists(); -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Exportation/JJDataExportation.cs b/src/MasterData.Core/UI/Components/Exportation/JJDataExportation.cs index 093851af8..ac7b80cd9 100644 --- a/src/MasterData.Core/UI/Components/Exportation/JJDataExportation.cs +++ b/src/MasterData.Core/UI/Components/Exportation/JJDataExportation.cs @@ -1,4 +1,6 @@ -using System; +#nullable disable warnings + +using System; using System.Collections.Generic; using System.IO; using System.Threading; @@ -9,23 +11,20 @@ using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Bootstrap.Models; using JJConsulting.Html.Extensions; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Data.Entity.Repository; using JJMasterData.Commons.Extensions; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Commons.Tasks; using JJMasterData.Commons.Util; using JJMasterData.Core.Configuration.Options; -using JJMasterData.Core.DataDictionary; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Exportation; using JJMasterData.Core.DataManager.Exportation.Abstractions; using JJMasterData.Core.DataManager.Exportation.Configuration; using JJMasterData.Core.DataManager.Expressions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Events.Args; - using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -42,7 +41,7 @@ public class JJDataExportation : ProcessComponent /// /// Event fired when the cell is rendered. /// - public event AsyncEventHandler OnRenderCellAsync; + public event EventHandler OnRenderCell; #endregion #region "Properties" @@ -62,6 +61,8 @@ public ExportOptions ExportOptions internal DataExportationScripts Scripts => field ??= new DataExportationScripts(this); internal IComponentFactory ComponentFactory { get; } + internal IFileStorage FileStorage { get; } + public IUrlHelper UrlHelper { get; } public DataExportationWriterFactory DataExportationWriterFactory { get; } #endregion @@ -70,35 +71,39 @@ public ExportOptions ExportOptions internal JJDataExportation( FormElement formElement, IMasterDataUser masterDataUser, + IUrlHelper urlHelper, ExpressionsService expressionsService, IOptionsSnapshot masterDataOptions, IBackgroundTaskManager backgroundTaskManager, IStringLocalizer stringLocalizer, IComponentFactory componentFactory, ILoggerFactory loggerFactory, - IHttpContext currentContext, + IHttpContextAccessor httpContextAccessor, IEncryptionService encryptionService, + IFileStorage fileStorage, DataExportationWriterFactory dataExportationWriterFactory) : - base(currentContext, masterDataUser, expressionsService, backgroundTaskManager, loggerFactory.CreateLogger(),encryptionService,stringLocalizer) + base(httpContextAccessor, masterDataUser, expressionsService, backgroundTaskManager, loggerFactory.CreateLogger(),encryptionService,stringLocalizer) { + FileStorage = fileStorage; + UrlHelper = urlHelper; DataExportationWriterFactory = dataExportationWriterFactory; ComponentFactory = componentFactory; - CurrentContext = currentContext; + HttpContextAccessor = httpContextAccessor; MasterDataOptions = masterDataOptions.Value; FormElement = formElement; } #endregion - protected override Task BuildResultAsync() + protected override async Task BuildResultAsync() { ComponentResult result; if (IsRunning()) result = new ContentComponentResult(new DataExportationLog(this).GetLoadingHtml()); else - result = new ContentComponentResult(new DataExportationSettings(this).GetHtmlBuilder()); + result = new ContentComponentResult(await new DataExportationSettings(this).GetHtmlBuilderAsync()); - return Task.FromResult(result); + return result; } internal static JJIcon GetFileIcon(string ext) @@ -110,31 +115,30 @@ internal static JJIcon GetFileIcon(string ext) return new JJIcon(FontAwesomeIcon.FileTextO); } - internal string GetDownloadUrl(string filePath) + internal string GetDownloadUrl(string fileName) { - var downloader = ComponentFactory.Downloader.Create(); - downloader.FilePath = filePath; - return downloader.GetDownloadUrl(); + return UrlHelper.ActionLink("Exportation", "File", new { Area = "MasterData", elementName = FormElement.Name, fileName }); } private string GetFinishedMessageHtml(DataExportationReporter reporter) { if (!reporter.HasError) { - string url = GetDownloadUrl(reporter.FilePath); + string url = GetDownloadUrl(reporter.FileName); var html = new HtmlBuilder(HtmlTag.Div); if (reporter.HasError) { - var panel = new JJValidationSummary(); - panel.ShowCloseButton = false; - panel.Title = reporter.Message; + var panel = new JJValidationSummary + { + ShowCloseButton = false, + Title = reporter.Message + }; html.AppendComponent(panel); } else { - var file = new FileInfo(reporter.FilePath); - var icon = GetFileIcon(file.Extension); + var icon = GetFileIcon(Path.GetExtension(reporter.FileName)); icon.CssClass = "fa-3x "; html.Append(HtmlTag.Div, div => @@ -176,7 +180,7 @@ private string GetFinishedMessageHtml(DataExportationReporter reporter) a.WithAttribute("href", url); a.AppendComponent(icon); a.Append(HtmlTag.Br); - a.AppendText(file.Name); + a.AppendText(reporter.FileName); }); div.Append(HtmlTag.Br); div.Append(HtmlTag.Br); @@ -216,37 +220,28 @@ private string GetFinishedMessageHtml(DataExportationReporter reporter) private DataExportationWriterBase CreateWriter() { - DataExportationWriterFactory.OnRenderCellAsync += OnRenderCellAsync; + DataExportationWriterFactory.OnRenderCell += OnRenderCell; return DataExportationWriterFactory.GetInstance(this); } public async Task ExecuteExportationAsync(DictionaryListResult result) { var exporter = CreateWriter(); - -#if NETFRAMEWORK - exporter.HttpContext = System.Web.HttpContext.Current; -#endif exporter.DataSource = result.Data; exporter.TotalOfRecords = result.TotalOfRecords; await exporter.RunWorkerAsync(CancellationToken.None); - var downloader = ComponentFactory.Downloader.Create(); - downloader.FilePath = exporter.ProcessReporter.FilePath; - - return downloader.GetDirectDownloadResult(); + var stream = await exporter.OpenReadAsync(); + return new FileStreamComponentResult(stream, exporter.ProcessReporter.FileName); } - internal void ExportFileInBackground(Dictionary filter, OrderByData orderByData) + internal void ExportFileInBackground(Dictionary filter, OrderByData orderByData) { var exporter = CreateWriter(); exporter.CurrentFilter = filter; exporter.CurrentOrder = orderByData; -#if NETFRAMEWORK - exporter.HttpContext = System.Web.HttpContext.Current; -#endif BackgroundTaskManager.Run(ProcessKey, exporter); } @@ -274,4 +269,4 @@ internal DataExportationProgressDto GetCurrentProgress() return dto; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Factories/TitleFactory.cs b/src/MasterData.Core/UI/Components/Factories/TitleFactory.cs index 630b5887b..dabf3940c 100644 --- a/src/MasterData.Core/UI/Components/Factories/TitleFactory.cs +++ b/src/MasterData.Core/UI/Components/Factories/TitleFactory.cs @@ -1,7 +1,5 @@ -#nullable enable using System; using System.Collections.Generic; -using JJConsulting.FontAwesome; using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Models; using JJMasterData.Core.DataDictionary.Models; diff --git a/src/MasterData.Core/UI/Components/FileComponentResult.cs b/src/MasterData.Core/UI/Components/FileComponentResult.cs deleted file mode 100644 index 39f7df46d..000000000 --- a/src/MasterData.Core/UI/Components/FileComponentResult.cs +++ /dev/null @@ -1,32 +0,0 @@ -#nullable enable -#if NET -using System.IO; -using System.Threading.Tasks; -using JJMasterData.Commons.Util; -using Microsoft.AspNetCore.Mvc; -#endif - -namespace JJMasterData.Core.UI.Components; - -public sealed class FileComponentResult(string filePath) : ComponentResult -#if NET - ,IActionResult -#endif -{ - private string FilePath { get; } = filePath; - public override string Content => FilePath; - -#if NET - public Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) - { - var fileName = Path.GetFileName(FilePath); - - var fileContentResult = new PhysicalFileResult(FilePath, MimeTypeUtil.GetMimeType(fileName)) - { - FileDownloadName = fileName - }; - - return fileContentResult.ExecuteResultAsync(context); - } -#endif -} \ No newline at end of file diff --git a/src/MasterData.Core/UI/Components/FileStreamComponentResult.cs b/src/MasterData.Core/UI/Components/FileStreamComponentResult.cs new file mode 100644 index 000000000..5abccf635 --- /dev/null +++ b/src/MasterData.Core/UI/Components/FileStreamComponentResult.cs @@ -0,0 +1,23 @@ +using System.IO; +using System.Threading.Tasks; +using JJMasterData.Commons.Util; + + +namespace JJMasterData.Core.UI.Components; + +public class FileStreamComponentResult( + Stream stream, + string fileName) : ComponentResult, IActionResult +{ + public override string Content => fileName; + + public Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) + { + var fileStreamResult = new FileStreamResult(stream, MimeTypeUtil.GetMimeType(fileName)) + { + FileDownloadName = fileName + }; + + return fileStreamResult.ExecuteResultAsync(context); + } +} diff --git a/src/MasterData.Core/UI/Components/FormView/FormViewFactory.cs b/src/MasterData.Core/UI/Components/FormView/FormViewFactory.cs index cb7ffe007..e2749c4c0 100644 --- a/src/MasterData.Core/UI/Components/FormView/FormViewFactory.cs +++ b/src/MasterData.Core/UI/Components/FormView/FormViewFactory.cs @@ -11,8 +11,6 @@ using JJMasterData.Core.DataManager.Services; using JJMasterData.Core.Events.Abstractions; using JJMasterData.Core.Events.Args; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.Tasks; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -20,7 +18,7 @@ namespace JJMasterData.Core.UI.Components; internal sealed class FormViewFactory( - IHttpContext currentContext, + IHttpContextAccessor currentContext, IMasterDataUser masterDataUser, IEntityRepository entityRepository, IDataDictionaryRepository dataDictionaryRepository, @@ -29,8 +27,9 @@ internal sealed class FormViewFactory( FormValuesService formValuesService, FieldValuesService fieldValuesService, ExpressionsService expressionsService, - HtmlTemplateService htmlTemplateService, + HtmlTemplateActionService htmlTemplateService, IEnumerable pluginHandlers, + UploadViewManager uploadViewManager, IStringLocalizer stringLocalizer, IOptionsSnapshot options, ILoggerFactory loggerFactory, @@ -53,6 +52,7 @@ public JJFormView Create(FormElement formElement) expressionsService, htmlTemplateService, pluginHandlers, + uploadViewManager, options, stringLocalizer, loggerFactory.CreateLogger(), @@ -78,6 +78,6 @@ private ValueTask SetFormEventHandlerAsync(JJFormView formView, FormElement form return formEventHandler.OnFormElementLoadAsync(formView, new FormElementLoadEventArgs(formElement))!; } - return ValueTaskHelper.CompletedTask; + return ValueTask.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/FormView/FormViewRelationshipLayout.cs b/src/MasterData.Core/UI/Components/FormView/FormViewRelationshipLayout.cs index 04cb02c65..b5fcc73dc 100644 --- a/src/MasterData.Core/UI/Components/FormView/FormViewRelationshipLayout.cs +++ b/src/MasterData.Core/UI/Components/FormView/FormViewRelationshipLayout.cs @@ -1,5 +1,4 @@ -#nullable enable - +#nullable disable warnings using System; using System.Collections.Generic; using System.Linq; @@ -58,7 +57,7 @@ public async Task GetRelationshipsResult() private async Task GetTabRelationshipsResult() { - var tabNav = new JJMasterDataTabNav(parentFormView.FormValues) + var tabNav = new JJMasterDataTabNav(parentFormView.CurrentContext) { Name = $"relationships-tab-nav-{parentFormView.DataPanel.Name}" }; @@ -102,7 +101,7 @@ private string GetExpressionValue(string? expression) switch (relationship.Panel.Layout) { case PanelLayout.Collapse: - var collapse = new JJMasterDataCollapsePanel(parentFormView.CurrentContext.Request.Form) + var collapse = new JJMasterDataCollapsePanel(parentFormView.CurrentContext) { Name = $"{relationship.ElementRelationship?.ChildElement ?? parentFormView.Name}-collapse-panel", Title = GetExpressionValue(relationship.Panel.Title), @@ -168,13 +167,13 @@ await parentFormView.ComponentFactory.FormView.CreateAsync(relationship.ElementR childFormView.CurrentActionMap = null; var filter = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - foreach (var col in relationship.ElementRelationship.Columns.Where(col => - parentPanel.Values.ContainsKey(col.PkColumn))) + + foreach (var col in relationship.ElementRelationship.Columns) { - var value = parentPanel.Values[col.PkColumn]; - filter[col.FkColumn] = value; + if (parentPanel.Values.TryGetValue(col.PkColumn, out var value)) + filter[col.FkColumn] = value; } - + switch (relationship.ViewType) { case RelationshipViewType.Insert: diff --git a/src/MasterData.Core/UI/Components/FormView/FormViewScripts.cs b/src/MasterData.Core/UI/Components/FormView/FormViewScripts.cs index 2f7b2b45e..7ac8c120f 100644 --- a/src/MasterData.Core/UI/Components/FormView/FormViewScripts.cs +++ b/src/MasterData.Core/UI/Components/FormView/FormViewScripts.cs @@ -1,7 +1,5 @@ -#nullable enable using System.Collections.Generic; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Routing; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/FormView/JJFormView.cs b/src/MasterData.Core/UI/Components/FormView/JJFormView.cs index 6d6a39be2..c4e0c53b4 100644 --- a/src/MasterData.Core/UI/Components/FormView/JJFormView.cs +++ b/src/MasterData.Core/UI/Components/FormView/JJFormView.cs @@ -1,5 +1,4 @@ -#nullable enable - + // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global // ReSharper disable EventNeverSubscribedTo.Global @@ -30,20 +29,13 @@ using JJMasterData.Core.DataManager.Services; using JJMasterData.Core.Events.Abstractions; using JJMasterData.Core.Events.Args; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.Logging; -using JJMasterData.Core.Tasks; using JJMasterData.Core.UI.Events.Args; using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -#if NET48 -using JJMasterData.Commons.Configuration; -#endif - namespace JJMasterData.Core.UI.Components; /// @@ -146,13 +138,14 @@ public event AsyncEventHandler? OnAfterDeleteAsync private readonly FormValuesService _formValuesService; private readonly FieldValuesService _fieldValuesService; - private readonly HtmlTemplateService _htmlTemplateService; + private readonly HtmlTemplateActionService _htmlTemplateService; private readonly IEnumerable _pluginHandlers; private readonly MasterDataCoreOptions _options; private readonly ILogger _logger; private readonly IDataDictionaryRepository _dataDictionaryRepository; private readonly IMasterDataUser _masterDataUser; private readonly FormService _formService; + private readonly UploadViewManager _uploadViewManager; #endregion @@ -299,7 +292,11 @@ private async ValueTask RenderInsertActionAtGrid(object _, GridRenderEventArgs a DataPanel.PageState = PageState.Insert; - var result = await GetFormResult(formStateData.Values, DataPanel.Errors, PageState.Insert, true); + var values = new Dictionary(formStateData.Values, StringComparer.InvariantCultureIgnoreCase); + + DataHelper.CopyIntoDictionary(values, formStateData.UserValues); + + var result = await GetFormResult(values, DataPanel.Errors, PageState.Insert, true); if (result is HtmlComponentResult htmlComponentResult) args.HtmlBuilder.Append(htmlComponentResult.HtmlBuilder); @@ -312,12 +309,14 @@ public PageState PageState { get { - if (_pageState is null && - CurrentContext.Request.Form.TryGetValue($"form-view-page-state-{Name}", out var formPageState)) - _pageState = (PageState)int.Parse(formPageState); + if (_pageState is null && CurrentContext.HttpContext!.Request.HasFormContentType && + CurrentContext.HttpContext!.Request.Form.TryGetValue($"form-view-page-state-{Name}", out var formPageState)) + { + _pageState = (PageState)int.Parse(formPageState.ToString()); + } if (_pageState is null && - CurrentContext.Request.QueryString.TryGetValue($"{FormElement.Name}_PageState", + CurrentContext.HttpContext!.Request.Query.TryGetValue($"{FormElement.Name}_PageState", out var queryStringPageState)) { if (Enum.TryParse(queryStringPageState, ignoreCase: true, out PageState pageState)) @@ -335,8 +334,8 @@ internal ActionMap? CurrentActionMap { if (_currentActionMap != null || _isCustomCurrentAction) return _currentActionMap; - - var encryptedActionMap = CurrentContext.Request.Form[$"current-action-map-{Name}"]; + + var encryptedActionMap = CurrentContext.HttpContext!.Request.GetFormValue($"current-action-map-{Name}"); if (string.IsNullOrEmpty(encryptedActionMap)) return null; @@ -373,7 +372,7 @@ public RouteContext RouteContext if (field != null) return field; - var factory = new RouteContextFactory(CurrentContext.Request.QueryString, EncryptionService); + var factory = new RouteContextFactory(CurrentContext, EncryptionService); field = factory.Create(); return field; @@ -397,9 +396,10 @@ internal RelationshipType RelationshipType get { if (_relationshipType is null && - CurrentContext.Request.Form.TryGetValue($"form-view-relationship-type-{Name}", + CurrentContext.HttpContext!.Request.HasFormContentType && + CurrentContext.HttpContext!.Request.Form.TryGetValue($"form-view-relationship-type-{Name}", out var relationshipType)) - _relationshipType = (RelationshipType)int.Parse(relationshipType); + _relationshipType = (RelationshipType)int.Parse(relationshipType.ToString()); return _relationshipType ?? RelationshipType.Parent; } @@ -409,8 +409,8 @@ internal RelationshipType RelationshipType internal bool IsInsertAtGridView => PageState is PageState.List && FormElement.Options.GridToolbarActions.InsertAction.ShowOpenedAtGrid; - internal IHttpContext CurrentContext { get; } - internal IFormValues FormValues => CurrentContext.Request.Form; + internal IHttpContextAccessor CurrentContext { get; } + internal IFormCollection FormValues => CurrentContext.HttpContext!.Request.Form; internal IEncryptionService EncryptionService { get; } internal IComponentFactory ComponentFactory { get; } internal IEntityRepository EntityRepository { get; } @@ -424,7 +424,7 @@ internal RelationshipType RelationshipType public JJFormView( FormElement formElement, - IHttpContext currentContext, + IHttpContextAccessor currentContext, IMasterDataUser masterDataUser, IEntityRepository entityRepository, IDataDictionaryRepository dataDictionaryRepository, @@ -433,8 +433,9 @@ public JJFormView( FormValuesService formValuesService, FieldValuesService fieldValuesService, ExpressionsService expressionsService, - HtmlTemplateService htmlTemplateService, + HtmlTemplateActionService htmlTemplateService, IEnumerable pluginHandlers, + UploadViewManager uploadViewManager, IOptionsSnapshot options, IStringLocalizer stringLocalizer, ILogger logger, @@ -457,6 +458,7 @@ public JJFormView( _fieldValuesService = fieldValuesService; _htmlTemplateService = htmlTemplateService; _pluginHandlers = pluginHandlers; + _uploadViewManager = uploadViewManager; _options = options.Value; _logger = logger; _dataDictionaryRepository = dataDictionaryRepository; @@ -485,7 +487,7 @@ protected override async Task BuildResultAsync() private async Task GetChildFormView() { - var childFormView = await ComponentFactory.FormView.CreateAsync(RouteContext.ElementName); + var childFormView = await ComponentFactory.FormView.CreateAsync(RouteContext.ElementName!); childFormView.FormElement.ParentName = RouteContext.ParentElementName; @@ -508,7 +510,7 @@ private async Task GetChildFormView() childFormView.GridView.TableActions.Add(new InsertSelectionAction()); childFormView.GridView.ToolbarActions.Add(GetInsertSelectionBackAction()); - childFormView.GridView.OnRenderActionAsync += InsertSelectionOnRenderAction; + childFormView.GridView.OnRenderAction += InsertSelectionOnRenderAction; return childFormView; } @@ -524,7 +526,7 @@ internal async Task GetFormResultAsync() case ComponentContext.LookupDescription: return await DataPanel.GetResultAsync(); case ComponentContext.UrlRedirect: - return await DataPanel.GetUrlRedirectResult(CurrentActionMap); + return await DataPanel.GetUrlRedirectResult(CurrentActionMap!); case ComponentContext.DataPanelReload: return await GetReloadPanelResultAsync(); case ComponentContext.DataExportation: @@ -534,7 +536,7 @@ internal async Task GetFormResultAsync() case ComponentContext.SearchBoxFilter: return await GetGridViewResult(); case ComponentContext.DownloadFile: - return ComponentFactory.Downloader.Create().GetDownloadResult(); + return await ComponentFactory.Downloader.Create().GetDownloadResultAsync(); case ComponentContext.AuditLogView: return await AuditLogView.GetResultAsync(); case ComponentContext.DataImportation or ComponentContext.DataImportationFileUpload: @@ -555,9 +557,9 @@ internal async Task GetReloadPanelResultAsync() else values = await GetFormValuesAsync(); - var fieldName = CurrentContext.Request.QueryString["fieldName"]; + var fieldName = CurrentContext.HttpContext!.Request.Query["fieldName"]; - var field = FormElement.Fields[fieldName]; + var field = FormElement.Fields[fieldName!]; var scripts = new HtmlBuilder(); @@ -641,7 +643,9 @@ private async Task GetSaveActionResult() Dictionary errors; if (PageState is PageState.Insert || IsInsertAtGridView) + { errors = await InsertFormValuesAsync(values); + } else errors = await UpdateFormValuesAsync(values); @@ -724,13 +728,13 @@ private void AppendInsertSuccessAlert(HtmlBuilder htmlBuilder) htmlBuilder.AppendScript(Scripts.GetShowInsertSuccessScript()); } - private Task GetCancelActionResult() + private async Task GetCancelActionResult() { PageState = PageState.List; - ClearTempFiles(); + _ = _uploadViewManager.ClearTemporaryFilesAsync(FormElement); - return GridView.GetResultAsync(); + return await GridView.GetResultAsync(); } private Task GetBackActionResult() @@ -951,7 +955,7 @@ private void SetEditMode() private bool ContainsHiddenPkValues() { - return CurrentContext.Request.Form[$"data-panel-pk-values-{FormElement.Name}"] is not null; + return !string.IsNullOrEmpty(CurrentContext.HttpContext!.Request.GetFormValue($"data-panel-pk-values-{FormElement.Name}")); } private async Task GetUpdateResult() @@ -969,7 +973,7 @@ private async Task GetUpdateResult() var filters = await GetFiltersWithDefaultValues(PageState.Update); - var letter = await _formService.GetAsync(FormElement, filters); + var letter = await _formService.GetAsync(FormElement, filters!); values = letter.Result!; var errors = letter.Errors; if (errors.Count > 0) @@ -1017,7 +1021,7 @@ private async Task GetDefaultResult(Dictionary var containsGridAction = false; if (GridView.TableActions.Any(a => a is InsertSelectionAction)) { - containsGridAction = !string.IsNullOrEmpty(CurrentContext.Request.Form[$"grid-view-action-map-{Name}"]); + containsGridAction = !string.IsNullOrEmpty(CurrentContext.HttpContext!.Request.GetFormValue($"grid-view-action-map-{Name}")); } if (PageState is PageState.List || containsGridAction) @@ -1042,7 +1046,7 @@ private async Task GetDefaultResult(Dictionary private bool IsReloadFields() { - return CurrentContext.Request.Form.ContainsFormValues() && + return CurrentContext.HttpContext!.Request.HasFormContentType && DataPanel.PageState is not PageState.View && CurrentAction is not PluginAction; } @@ -1113,11 +1117,12 @@ private async ValueTask GetInsertSelectionFormView() if (_insertSelectionFormView != null) return _insertSelectionFormView; - _insertSelectionFormView = - await ComponentFactory.FormView.CreateAsync(GridView.InsertAction.ElementNameToSelect); + var elementNameToSelect = GridView.InsertAction.ElementNameToSelect ?? throw new JJMasterDataException("Element name to select cannot be null."); + + _insertSelectionFormView = await ComponentFactory.FormView.CreateAsync(elementNameToSelect); _insertSelectionFormView.FormElement.ParentName = FormElement.Name; _insertSelectionFormView.UserValues = UserValues; - _insertSelectionFormView.GridView.OnRenderActionAsync += InsertSelectionOnRenderAction; + _insertSelectionFormView.GridView.OnRenderAction += InsertSelectionOnRenderAction; _insertSelectionFormView.GridView.ToolbarActions.Add(GetInsertSelectionBackAction()); _insertSelectionFormView.GridView.TableActions.Add(new InsertSelectionAction()); @@ -1139,10 +1144,10 @@ private ScriptAction GetInsertSelectionBackAction() private async Task GetInsertSelectionResult() { - var insertValues = EncryptionService.DecryptDictionary(FormValues[$"form-view-insert-selection-values-{Name}"]); + var insertValues = EncryptionService.DecryptDictionary(FormValues[$"form-view-insert-selection-values-{Name}"]!); var html = new HtmlBuilder(HtmlTag.Div); - var childElementName = GridView.ToolbarActions.InsertAction.ElementNameToSelect; + var childElementName = GridView.ToolbarActions.InsertAction.ElementNameToSelect ?? throw new JJMasterDataException("Element name to select cannot be null."); var childElement = await _dataDictionaryRepository.GetFormElementAsync(childElementName); var selectionValues = await EntityRepository.GetFieldsAsync(childElement, insertValues); @@ -1211,7 +1216,7 @@ private async Task GetViewResult() PageState = PageState.View; var filters = await GetFiltersWithDefaultValues(PageState.View); - var letter = await _formService.GetAsync(FormElement, filters); + var letter = await _formService.GetAsync(FormElement, filters!); var values = letter.Result!; var errors = letter.Errors; if (errors.Count > 0) @@ -1219,7 +1224,7 @@ private async Task GetViewResult() return await GetGridResultWithErrors(errors); } - return await GetFormResult(values, PageState, false); + return await GetFormResult(values!, PageState, false); } private async Task GetDeleteResult() @@ -1272,7 +1277,7 @@ private async Task GetAuditLogResult() { var html = new HtmlBuilder(HtmlTag.Div); - var logDetailsHtml = await AuditLogView.GetLogDetailsHtmlAsync(actionMap?.PkFieldValues); + var logDetailsHtml = await AuditLogView.GetLogDetailsHtmlAsync(actionMap?.PkFieldValues!); html.Append(logDetailsHtml); @@ -1614,13 +1619,13 @@ private async ValueTask GetFormToolbarAsync(List actions return toolbar; } - private ValueTask InsertSelectionOnRenderAction(object? sender, ActionEventArgs args) + private void InsertSelectionOnRenderAction(object? sender, ActionEventArgs args) { if (sender is not JJGridView gridView) - return ValueTaskHelper.CompletedTask; + return; if (args.ActionName is not InsertSelectionAction.ActionName) - return ValueTaskHelper.CompletedTask; + return; args.LinkButton.Tooltip = Localizer["Select"]; @@ -1628,10 +1633,25 @@ private ValueTask InsertSelectionOnRenderAction(object? sender, ActionEventArgs args.LinkButton.OnClientClick = Scripts.GetInsertSelectionScript(pkValues!); - return ValueTaskHelper.CompletedTask; } - + /// + /// Insert or updates the records in the database. + /// + /// The list of errors. + public async Task> InsertOrReplaceFormValuesAsync(Dictionary values) + { + var dataContext = new DataContext(CurrentContext.HttpContext!.Request, DataContextSource.Form, UserId); + var result = await _formService.InsertOrReplaceAsync(FormElement, values, dataContext); + if (result.Errors.Count == 0) + { + await _uploadViewManager.PromoteDraftFilesAsync(FormElement, DataPanel.Values); + } + + UrlRedirect = result.UrlRedirect; + return result.Errors; + } + /// /// Insert the records in the database. /// @@ -1640,8 +1660,13 @@ public async Task> InsertFormValuesAsync( Dictionary values, bool validateFields = true) { - var dataContext = new DataContext(CurrentContext.Request, DataContextSource.Form, UserId); + var dataContext = new DataContext(CurrentContext.HttpContext!.Request, DataContextSource.Form, UserId); var result = await _formService.InsertAsync(FormElement, values, dataContext, validateFields); + if (result.Errors.Count == 0) + { + await _uploadViewManager.PromoteDraftFilesAsync(FormElement, DataPanel.Values); + } + UrlRedirect = result.UrlRedirect; return result.Errors; } @@ -1652,19 +1677,27 @@ public async Task> InsertFormValuesAsync( /// The list of errors. public async Task> UpdateFormValuesAsync(Dictionary values) { - var result = await _formService.UpdateAsync(FormElement, values, - new DataContext(CurrentContext.Request, DataContextSource.Form, UserId)); + var dataContext = new DataContext(CurrentContext.HttpContext!.Request, DataContextSource.Form, UserId); + var result = await _formService.UpdateAsync(FormElement, values, dataContext); + if (result.Errors.Count == 0) + { + await _uploadViewManager.PromoteDraftFilesAsync(FormElement, DataPanel.Values); + } + UrlRedirect = result.UrlRedirect; return result.Errors; } public async Task> DeleteFormValuesAsync(Dictionary? filter) { - var values = - await _fieldValuesService.MergeWithExpressionValuesAsync(FormElement, - new FormStateData(filter!, UserValues, PageState.Delete)); - var result = await _formService.DeleteAsync(FormElement, values, - new DataContext(CurrentContext.Request, DataContextSource.Form, UserId)); + var dataContext = new DataContext(CurrentContext.HttpContext!.Request, DataContextSource.Form, UserId); + var formStateData = new FormStateData(filter!, UserValues, PageState.Delete); + var values = await _fieldValuesService.MergeWithExpressionValuesAsync(FormElement, formStateData); + var result = await _formService.DeleteAsync(FormElement, values!, dataContext); + if (result.Errors.Count == 0) + { + await _uploadViewManager.ClearTemporaryFilesAsync(FormElement); + } UrlRedirect = result.UrlRedirect; return result.Errors; } @@ -1680,23 +1713,19 @@ await _fieldValuesService.MergeWithExpressionValuesAsync(FormElement, return values; } - - public Dictionary ValidateFields(Dictionary values, PageState pageState) + + public Dictionary ValidateFields(Dictionary values, PageState pageState) { DataPanel.Values = values; var errors = DataPanel.ValidateFields(values, pageState); return errors; } - - private void ClearTempFiles() + + public async ValueTask> ValidateFieldsAsync(Dictionary values) { - var uploadFields = FormElement.Fields.FindAll(x => x.Component == FormComponent.File); - foreach (var field in uploadFields) - { - string sessionName = $"{field.Name}-upload-view_jjfiles"; - if (CurrentContext.Session.HasKey(sessionName)) - CurrentContext.Session[sessionName] = null; - } + DataPanel.Values = values; + var errors = await DataPanel.ValidateFieldsAsync(values); + return errors; } public async ValueTask GetFormStateDataAsync() @@ -1746,7 +1775,7 @@ await _formValuesService.GetFormValuesWithMergedValuesAsync(FormElement, initial public Dictionary GetRelationValuesFromForm() { - var encryptedRelationValues = CurrentContext.Request.Form[$"form-view-relation-values-{FormElement.Name}"]; + var encryptedRelationValues = CurrentContext.HttpContext!.Request.GetFormValue($"form-view-relation-values-{FormElement.Name}"); if (string.IsNullOrEmpty(encryptedRelationValues)) return new Dictionary(); diff --git a/src/MasterData.Core/UI/Components/GridView/GridCaptionView.cs b/src/MasterData.Core/UI/Components/GridView/GridCaptionView.cs index 3e9809fad..56866592b 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridCaptionView.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridCaptionView.cs @@ -1,13 +1,12 @@ -using System.Linq; +#nullable disable warnings +using System.Linq; using System.Threading.Tasks; using JJConsulting.FontAwesome; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; -using JJMasterData.Core.DataDictionary; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Html; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -56,7 +55,7 @@ private async Task GetCaptionHtmlBuilder(FormElementField field) { div.WithStyle( "height:2.5rem"); - div.AppendComponent(new JJIcon(item.Icon, item.IconColor) + div.AppendComponent(new JJIcon(item.Icon.GetValueOrDefault(), item.IconColor ?? string.Empty) { CssClass = "fa-fw fa-2x" }); diff --git a/src/MasterData.Core/UI/Components/GridView/GridFilter.cs b/src/MasterData.Core/UI/Components/GridView/GridFilter.cs index ef77cc54d..4b02bd3ef 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridFilter.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridFilter.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; @@ -17,8 +18,6 @@ using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Events.Args; using Microsoft.Extensions.Localization; @@ -33,11 +32,11 @@ internal sealed class GridFilter(JJGridView gridView) internal const string FilterFieldPrefix = "filter_"; - private readonly IHttpContext _currentContext = gridView.CurrentContext; + private readonly IHttpContextAccessor _currentContext = gridView.CurrentContext; private readonly IStringLocalizer _stringLocalizer = gridView.StringLocalizer; - private Dictionary _currentFilter; - private Dictionary _userFilters; + private Dictionary? _currentFilter; + private Dictionary? _userFilters; public string Name => gridView.Name + "-filter"; @@ -62,7 +61,7 @@ internal async ValueTask GetFilterHtml() return filterHtml.Append(await GetDefaultFilter()); } - public async ValueTask> GetCurrentFilterAsync() + public async ValueTask> GetCurrentFilterAsync() { if (_currentFilter != null) return _currentFilter; @@ -72,7 +71,7 @@ public async ValueTask> GetCurrentFilterAsync() DataHelper.CopyIntoDictionary(_currentFilter, _userFilters); //Action is captured here, because the user can call GetCurrentFilterAsync before GetResultAsync() - var currentFilterAction = _currentContext.Request.Form[$"grid-view-filter-action-{gridView.Name}"]; + var currentFilterAction = _currentContext.HttpContext!.Request.GetFormValue($"grid-view-filter-action-{gridView.Name}"); switch (currentFilterAction) { case FilterActionName: @@ -86,20 +85,29 @@ public async ValueTask> GetCurrentFilterAsync() return _currentFilter; } - var sessionFilter = _currentContext.Session.GetSessionValue>( - $"jjcurrentfilter_{gridView.Name}"); + var cookieFilter = _currentContext.HttpContext!.GetGridFilterCookie(gridView.Name); - if (sessionFilter != null && gridView.MaintainValuesOnLoad) + if (cookieFilter != null && gridView.MaintainValuesOnLoad) { - DataHelper.CopyIntoDictionary(_currentFilter, sessionFilter); + DataHelper.CopyIntoDictionary(_currentFilter, cookieFilter); return _currentFilter; } - if (sessionFilter != null && (_currentContext.Request.Form.ContainsFormValues() || IsDynamicPost())) + if (cookieFilter != null && (_currentContext.HttpContext!.Request.HasFormContentType || IsDynamicPost())) { - DataHelper.CopyIntoDictionary(_currentFilter, sessionFilter); + DataHelper.CopyIntoDictionary(_currentFilter, cookieFilter); return _currentFilter; } + + if (_currentContext.HttpContext!.Request.HasFormContentType || IsDynamicPost()) + { + var postedFilter = GetPostedFilterValues(); + if (postedFilter is not null) + { + await ApplyCurrentFilter(postedFilter); + return _currentFilter; + } + } await ApplyCurrentFilter(null); @@ -114,10 +122,10 @@ public void SetCurrentFilter(string name, object value) private bool IsDynamicPost() { - return !string.IsNullOrEmpty(_currentContext.Request.QueryString["routeContext"]); + return !string.IsNullOrEmpty(_currentContext.HttpContext!.Request.Query["routeContext"]); } - public async ValueTask ApplyCurrentFilter(Dictionary values) + public async ValueTask ApplyCurrentFilter(Dictionary? values) { _currentFilter ??= new Dictionary(); @@ -149,8 +157,9 @@ await gridView.FieldValuesService.MergeWithDefaultValuesAsync(gridView.FormEleme DataHelper.CopyIntoDictionary(values, defaultValues); DataHelper.CopyIntoDictionary(_currentFilter, values); - - _currentContext.Session.SetSessionValue($"jjcurrentfilter_{gridView.Name}", _currentFilter); + + if(gridView.MaintainValuesOnLoad) + _currentContext.HttpContext!.SetGridFilterCookie(gridView.Name, _currentFilter); } private async ValueTask GetDefaultFilter() @@ -199,7 +208,7 @@ private async ValueTask GetDefaultFilter() { Enabled = gridView.EnableFilter, Text = _stringLocalizer["Filter"], - IconClass = "fa fa-search", + IconClass = "fa fa-search text-primary", ShowAsButton = true, Type = LinkButtonType.Submit, OnClientClick = $"{gridView.Scripts.GetFilterScript()};" @@ -208,7 +217,7 @@ private async ValueTask GetDefaultFilter() var btnCancel = new JJLinkButton { Enabled = gridView.EnableFilter, - Text = _stringLocalizer["Clear Filter"], + Text = _stringLocalizer["Clear Filters"], IconClass = "fa fa-trash", ShowAsButton = true, Type = LinkButtonType.Button, @@ -217,7 +226,7 @@ private async ValueTask GetDefaultFilter() if (action.ShowAsCollapse) { - var hasFilter = await HasFilter(); + var hasFilter = HasFilter(values); var filterIcon = new JJIcon(FontAwesomeIcon.Filter) { CssClass = "text-info", @@ -233,7 +242,7 @@ private async ValueTask GetDefaultFilter() filterIcon.CssClass += " d-none"; } - var panel = new JJMasterDataCollapsePanel(_currentContext.Request.Form, $"filter-collapse-{gridView.Name}") + var panel = new JJMasterDataCollapsePanel(_currentContext, $"filter-collapse-{gridView.Name}") { Content = html, TitleIcon = filterIcon, @@ -276,7 +285,7 @@ private JJMasterDataCollapsePanel GetFilterScreenCollapse() body.WithCssClass("col-sm-12"); body.Append(GetHtmlToolBarSearch(isToolBar: false)); - var panel = new JJMasterDataCollapsePanel(_currentContext.Request.Form) + var panel = new JJMasterDataCollapsePanel(_currentContext) { Name = $"filter-collapse-{gridView.Name}", Content = body, @@ -291,7 +300,7 @@ public HtmlBuilder GetHtmlToolBarSearch(bool isToolBar = true) { var searchId = $"jjsearch_{gridView.Name}"; - var textBox = new JJTextBox(gridView.CurrentContext.Request.Form) + var textBox = new JJTextBox(gridView.CurrentContext) { Attributes = { @@ -301,7 +310,7 @@ public HtmlBuilder GetHtmlToolBarSearch(bool isToolBar = true) PlaceHolder = _stringLocalizer["Filter"], CssClass = "jj-icon-search", Name = searchId, - Text = _currentContext.Request.Form[searchId] + Text = _currentContext.HttpContext!.Request.GetFormValue(searchId) }; var html = new HtmlBuilder(); @@ -356,14 +365,10 @@ private async Task> GetFilterFormValues() //Relation Filters var values = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - var filters = _currentContext.Request.Form[$"grid-view-filters-{gridView.Name}"]; - if (!string.IsNullOrEmpty(filters)) - { - var filterJson = gridView.EncryptionService.DecryptStringWithUrlUnescape(filters); - values = JsonSerializer.Deserialize>(filterJson, MasterDataJsonSerializerOptions.Default)!; - } + DataHelper.CopyIntoDictionary(values, GetPostedFilterValues()); var fieldsFilter = gridView.FormElement.Fields.FindAll(x => x.Filter.Type != FilterMode.None); + RemoveCurrentFieldFilters(values, fieldsFilter); foreach (var field in fieldsFilter) { @@ -371,14 +376,14 @@ private async Task> GetFilterFormValues() if (field.Filter.Type == FilterMode.Range) { - var fromStringValue = _currentContext.Request.Form[$"{name}_from"]; + var fromStringValue = _currentContext.HttpContext!.Request.GetFormValue($"{name}_from"); if (!string.IsNullOrEmpty(fromStringValue)) { var fromValue = ParseFilterValue(field, fromStringValue); values.Add($"{field.Name}_from", fromValue); } - var toStringValue = _currentContext.Request.Form[$"{name}_to"]; + var toStringValue = _currentContext.HttpContext!.Request.GetFormValue($"{name}_to"); if (string.IsNullOrEmpty(toStringValue)) continue; @@ -388,7 +393,7 @@ private async Task> GetFilterFormValues() } else { - object value = _currentContext.Request.Form[name]; + object value = _currentContext.HttpContext!.Request.GetFormValue(name); switch (field.Component) { @@ -430,8 +435,30 @@ private async Task> GetFilterFormValues() return values; } + private Dictionary? GetPostedFilterValues() + { + var filters = _currentContext.HttpContext!.Request.GetFormValue($"grid-view-filters-{gridView.Name}"); + if (string.IsNullOrEmpty(filters)) + return null; + + var filterJson = gridView.EncryptionService.DecryptString(filters); + return JsonSerializer.Deserialize>(filterJson, MasterDataJsonSerializerOptions.Default); + } + + private static void RemoveCurrentFieldFilters( + Dictionary values, + List fieldsFilter) + { + foreach (var field in fieldsFilter) + { + values.Remove(field.Name); + values.Remove($"{field.Name}_from"); + values.Remove($"{field.Name}_to"); + } + } + - private Dictionary GetFilterQueryString() + private Dictionary? GetFilterQueryString() { Dictionary values = null; var fieldsFilter = gridView.FormElement.Fields.FindAll(x => x.Filter.Type != FilterMode.None); @@ -441,8 +468,8 @@ private Dictionary GetFilterQueryString() if (filter.Filter.Type == FilterMode.Range) { - var fromString = _currentContext.Request.QueryString[$"{name}_from"]; - if (values == null && fromString != null) + var fromString = _currentContext.HttpContext!.Request.Query[$"{name}_from"]; + if (values == null && !string.IsNullOrEmpty(fromString.ToString())) values = new Dictionary(); if (!string.IsNullOrEmpty(fromString)) @@ -450,7 +477,7 @@ private Dictionary GetFilterQueryString() values.Add($"{filter.Name}_from", fromString); } - var toString = _currentContext.Request.QueryString[$"{name}_to"]; + var toString = _currentContext.HttpContext!.Request.Query[$"{name}_to"]; if (!string.IsNullOrEmpty(toString)) { values?.Add($"{filter.Name}_to", toString); @@ -458,7 +485,7 @@ private Dictionary GetFilterQueryString() } else { - var queryStringValue = _currentContext.Request.QueryString[name]; + var queryStringValue = _currentContext.HttpContext!.Request.Query[name]; if (string.IsNullOrEmpty(queryStringValue)) continue; @@ -471,11 +498,11 @@ private Dictionary GetFilterQueryString() return values; } - public async ValueTask HasFilter() + public bool HasFilter(Dictionary filters) { - foreach (var item in await GetCurrentFilterAsync()) + foreach (var item in filters) { - if (string.IsNullOrEmpty(item.Value.ToString())) + if (string.IsNullOrEmpty(item.Value?.ToString())) continue; if (!gridView.FormElement.Fields.TryGetField(item.Key, out var field)) @@ -487,4 +514,4 @@ public async ValueTask HasFilter() return false; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/GridPagination.cs b/src/MasterData.Core/UI/Components/GridView/GridPagination.cs index 4f903002a..0192f347e 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridPagination.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridPagination.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using JJConsulting.FontAwesome; @@ -7,8 +5,6 @@ using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; -using JJMasterData.Core.DataDictionary; -using JJMasterData.Core.Html; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/GridView/GridScripts.cs b/src/MasterData.Core/UI/Components/GridView/GridScripts.cs index cbd61856d..c712cb0bb 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridScripts.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridScripts.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Text; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Routing; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/GridView/GridSettingsForm.cs b/src/MasterData.Core/UI/Components/GridView/GridSettingsForm.cs index 631ed3cb9..60a3ffa99 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridSettingsForm.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridSettingsForm.cs @@ -1,8 +1,6 @@ using JJConsulting.Html; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Util; -using JJMasterData.Core.Http.Abstractions; - using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -12,7 +10,7 @@ namespace JJMasterData.Core.UI.Components; /// internal sealed class GridSettingsForm( string name, - IHttpContext currentContext, + IHttpContextAccessor currentContext, IStringLocalizer stringLocalizer) { private readonly string _tableTotalPerPage = $"{name}-table-regperpage"; @@ -26,13 +24,14 @@ internal sealed class GridSettingsForm( public GridSettings LoadFromForm() { var gridSettings = new GridSettings(); - var tableRegPerPage = currentContext.Request[_tableTotalPerPage]; - var tableTotalPageButtons = currentContext.Request[_tableTotalPaginationButtons]; - var tableBorder = currentContext.Request[_tableBorder]; - var tableRowsStriped = currentContext.Request[_tableRowsStriped]; - var tableRowHover = currentContext.Request[_tableRowHover]; - var tableIsHeaderFixed = currentContext.Request[_tableIsHeaderFixed]; - var tableIsCompact = currentContext.Request[_tableIsCompact]; + var form = currentContext.HttpContext!.Request.GetFormValue; + var tableRegPerPage = form(_tableTotalPerPage); + var tableTotalPageButtons = form(_tableTotalPaginationButtons); + var tableBorder = form(_tableBorder); + var tableRowsStriped = form(_tableRowsStriped); + var tableRowHover = form(_tableRowHover); + var tableIsHeaderFixed = form(_tableIsHeaderFixed); + var tableIsCompact = form(_tableIsCompact); if (int.TryParse(tableRegPerPage, out var totalPerPage)) gridSettings.RecordsPerPage = totalPerPage; @@ -49,7 +48,7 @@ public GridSettings LoadFromForm() } internal bool HasFormValues() => - currentContext.Request[_tableTotalPerPage] != null; + currentContext.HttpContext!.Request.HasFormContentType && currentContext.HttpContext!.Request.Form.TryGetValue(_tableTotalPerPage, out _); internal HtmlBuilder GetHtmlBuilder(bool isPaginationEnabled, GridSettings gridSettings) { @@ -178,7 +177,7 @@ private HtmlBuilder GetPaginationSelect(GridSettings gridSettings) private HtmlBuilder GetDataToggleElement(string name, string label, bool isChecked) { - var checkbox = new JJCheckBox(currentContext.Request.Form, stringLocalizer) + var checkbox = new JJCheckBox(currentContext, stringLocalizer) { Name = name, IsChecked = isChecked, @@ -188,4 +187,4 @@ private HtmlBuilder GetDataToggleElement(string name, string label, bool isCheck return checkbox.GetHtmlBuilder(); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/GridSortingConfig.cs b/src/MasterData.Core/UI/Components/GridView/GridSortingConfig.cs index d8b158dfb..255f8699f 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridSortingConfig.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridSortingConfig.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.FontAwesome; using JJConsulting.Html; diff --git a/src/MasterData.Core/UI/Components/GridView/GridSqlCommandAction.cs b/src/MasterData.Core/UI/Components/GridView/GridSqlCommandAction.cs index 02165e66e..0407abc29 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridSqlCommandAction.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridSqlCommandAction.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html.Bootstrap.Models; diff --git a/src/MasterData.Core/UI/Components/GridView/GridTable.cs b/src/MasterData.Core/UI/Components/GridView/GridTable.cs index 78672bc04..956d3a5ae 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridTable.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridTable.cs @@ -1,25 +1,28 @@ -#nullable enable +using System.Collections.Generic; using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Extensions; - +using JJMasterData.Core.DataDictionary.Models; namespace JJMasterData.Core.UI.Components; -internal sealed class GridTable(JJGridView gridView) +internal sealed class GridTable( + JJGridView gridView, + List visibleFields, + Dictionary filters) { internal GridSettings Settings { get; } = gridView.CurrentSettings; - internal GridTableHeader Header { get; } = new(gridView); + internal GridTableHeader Header { get; } = new(gridView, visibleFields, filters); - internal GridTableBody Body { get; } = new(gridView); + internal GridTableBody Body { get; } = new(gridView, visibleFields); - public async ValueTask GetHtmlBuilder() + public async ValueTask GetHtmlBuilderAsync() { var div = HtmlBuilder.Div(); div.WithCssClass("pt-1"); - div.WithCssClassIf(Settings is { IsResponsive: true, IsHeaderFixed: false }, "table-responsive"); - + div.WithCssClassIf(Settings is { IsResponsive: true, IsHeaderFixed: false }, "table-responsive"); + var table = HtmlBuilder.Table(); table.WithCssClass("table"); table.WithCssClassIf(Settings.IsCompact, "table-sm"); @@ -28,11 +31,11 @@ public async ValueTask GetHtmlBuilder() table.WithCssClassIf(Settings.ShowRowStriped, "table-striped"); table.WithCssClassIf(Settings.IsHeaderFixed, "table-fixed-header"); - table.Append(await Header.GetHtmlBuilderAsync()); + table.Append(Header.GetHtmlBuilder()); table.Append(await Body.GetHtmlBuilderAsync()); div.Append(table); - + return div; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/GridTableBody.cs b/src/MasterData.Core/UI/Components/GridView/GridTableBody.cs index fdbc5c70f..1e0688d02 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridTableBody.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridTableBody.cs @@ -1,5 +1,5 @@ -#nullable enable - +#nullable disable warnings +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -9,26 +9,26 @@ using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Data.Entity.Models; -using JJMasterData.Commons.Tasks; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Events.Args; using JJMasterData.Core.UI.Routing; namespace JJMasterData.Core.UI.Components; -internal sealed class GridTableBody(JJGridView gridView) +internal sealed class GridTableBody( + JJGridView gridView, + List visibleFields) { private readonly string _name = $"{gridView.Name}-table"; - public event AsyncEventHandler? OnRenderActionAsync; - public event AsyncEventHandler? OnRenderCellAsync; - public event AsyncEventHandler? OnRenderSelectedCellAsync; - public event AsyncEventHandler? OnRenderRowAsync; + public event EventHandler? OnRenderAction; + public event EventHandler? OnRenderCell; + public event EventHandler? OnRenderSelectedCell; + public event EventHandler? OnRenderRow; public async ValueTask GetHtmlBuilderAsync() { @@ -124,9 +124,9 @@ private async ValueTask GetRowHtml(Dictionary row, tr.AppendRange(await GetTdHtmlList(row, index)); - if (OnRenderRowAsync is not null) + if (OnRenderRow is not null) { - await OnRenderRowAsync(gridView, new() + OnRenderRow(gridView, new() { HtmlBuilder = tr, RowValues = row @@ -142,13 +142,14 @@ internal async ValueTask> GetTdHtmlList(Dictionary x.Order); var defaultAction = basicActions.FirstOrDefault(x => x is { IsVisible: true, IsDefaultOption: true }); - var onClickScript = await GetOnClickScript(formStateData, defaultAction); + + var onClickScript = GetOnClickScript(formStateData, defaultAction); var tdList = new List(); if (gridView.EnableMultiSelect) { - var checkBox = await GetMultiSelectCheckbox(row, index, values); + var checkBox = GetMultiSelectCheckbox(row, index, values); var td = new HtmlBuilder(HtmlTag.Td); td.WithCssClass("jj-checkbox"); @@ -164,7 +165,8 @@ internal async ValueTask> GetTdHtmlList(Dictionary> GetVisibleFieldsHtmlList( { var result = new List(); var formStateData = new FormStateData(values, gridView.UserValues, PageState.List); - foreach (var field in await gridView.GetVisibleFieldsAsync()) + foreach (var field in visibleFields) { var formattedValue = string.Empty; var stringValue = string.Empty; @@ -217,7 +219,10 @@ private async ValueTask GetGridFieldHtml(FormElementField field, if (!string.IsNullOrEmpty(field.GridRenderingTemplate)) { - var replacedTemplate = await gridView.HtmlTemplateService.RenderTemplate(field.GridRenderingTemplate!, formStateData.Values); + var replacedTemplate = await gridView.HtmlTemplateRenderer.RenderTemplate( + gridView.FormElement, + field, + formStateData.Values); cell = new HtmlBuilder(replacedTemplate, encode:false); } else @@ -229,7 +234,7 @@ private async ValueTask GetGridFieldHtml(FormElementField field, if (isDataIconWithIcon) { - cell = await GetDataItemIconCell(field.DataItem!, formStateData, stringValue); + cell = await GetDataItemIconCell(field.DataItem, formStateData, stringValue); } else if (field.DataFile is not null) { @@ -256,8 +261,7 @@ private async ValueTask GetGridFieldHtml(FormElementField field, { var selector = new FormElementFieldSelector(gridView.FormElement, field.Name); var gridValue = await gridView.FieldFormattingService.FormatGridValueAsync(selector, formStateData); - var gridStringValue = gridValue?.Trim() ?? string.Empty; - cell = new HtmlBuilder(gridStringValue, encode: false); + cell = new HtmlBuilder(gridValue, encode: false); break; } } @@ -265,7 +269,7 @@ private async ValueTask GetGridFieldHtml(FormElementField field, } - if (OnRenderCellAsync == null) + if (OnRenderCell == null) return cell; var args = new GridCellEventArgs @@ -276,7 +280,7 @@ private async ValueTask GetGridFieldHtml(FormElementField field, Sender = new JJText(stringValue) }; - await OnRenderCellAsync(this, args); + OnRenderCell(this, args); return args.HtmlResult ?? cell; } @@ -299,7 +303,7 @@ private async Task GetDataItemIconCell(FormElementDataItem dataItem if (dataItemValue != null) { cell = GetIconCell( - dataItemValue.Icon, + dataItemValue.Icon.GetValueOrDefault(), dataItemValue.IconColor ?? string.Empty, tooltip); @@ -357,11 +361,11 @@ private async ValueTask GetEditModeFieldHtml( control.CssClass = field.Name; - if (OnRenderCellAsync != null) + if (OnRenderCell != null) { var args = new GridCellEventArgs { Field = field, DataRow = row, Sender = control }; - await OnRenderCellAsync(gridView, args); + OnRenderCell(gridView, args); if (args.HtmlResult is not null) { @@ -380,24 +384,24 @@ private async ValueTask GetEditModeFieldHtml( return div; } - public async ValueTask> GetActionsHtmlListAsync(FormStateData formStateData) + private List GetActionsHtmlList(FormStateData formStateData) { List result = []; var basicActions = gridView.TableActions.OrderBy(x => x.Order).ToList(); var actionsWithoutGroup = basicActions.Where(x => x is { IsVisible: true, IsGroup: false }); var groupedActions = basicActions.FindAll(x => x is { IsVisible: true, IsGroup: true }); - result.AddRange(await GetActionsWithoutGroupHtmlAsync(actionsWithoutGroup, formStateData)); + result.AddRange( GetActionsWithoutGroupHtml(actionsWithoutGroup, formStateData)); if (groupedActions.Count > 0) { - result.Add(await GetActionsGroupHtmlAsync(groupedActions, formStateData)); + result.Add(GetActionsGroupHtml(groupedActions, formStateData)); } return result; } - private async ValueTask GetActionsGroupHtmlAsync( + private HtmlBuilder GetActionsGroupHtml( List actions, FormStateData formStateData) { @@ -413,34 +417,34 @@ private async ValueTask GetActionsGroupHtmlAsync( btnGroup.ShowAsButton = groupedAction.ShowAsButton; var linkButton = factory.CreateGridTableButton(groupedAction, gridView, formStateData); - if (OnRenderActionAsync != null) + if (OnRenderAction != null) { var args = new ActionEventArgs(groupedAction, linkButton, formStateData.Values); - await OnRenderActionAsync(gridView, args); + OnRenderAction(gridView, args); } btnGroup.Actions.Add(linkButton); } td.AppendComponent(btnGroup); + return td; } - private async ValueTask> GetActionsWithoutGroupHtmlAsync( - IEnumerable actionsWithoutGroup, FormStateData formStateData) + private IEnumerable GetActionsWithoutGroupHtml(IEnumerable actionsWithoutGroup, FormStateData formStateData) { var factory = gridView.ComponentFactory.ActionButton; - List result = []; + foreach (var action in actionsWithoutGroup) { var td = new HtmlBuilder(HtmlTag.Td); td.WithCssClass("table-action"); var link = factory.CreateGridTableButton(action, gridView, formStateData); - if (OnRenderActionAsync is not null) + if (OnRenderAction is not null) { var args = new ActionEventArgs(action, link, formStateData.Values); - await OnRenderActionAsync(gridView, args); + OnRenderAction(gridView, args); if (args.HtmlResult != null) { @@ -452,10 +456,8 @@ private async ValueTask> GetActionsWithoutGroupHtmlAsync( if (link != null) td.AppendComponent(link); - result.Add(td); + yield return td; } - - return result; } private static string GetTdStyle(FormElementField field) @@ -498,17 +500,17 @@ private static string GetTdStyle(FormElementField field) return string.Empty; } - private async ValueTask GetMultiSelectCheckbox(Dictionary row, int index, + private JJCheckBox GetMultiSelectCheckbox(Dictionary row, int index, Dictionary values) { var pkValues = DataHelper.ParsePkValues(gridView.FormElement, values, ';'); var td = new HtmlBuilder(HtmlTag.Td); td.WithCssClass("jj-checkbox"); - var checkBox = new JJCheckBox(gridView.CurrentContext.Request.Form, gridView.StringLocalizer) + var checkBox = new JJCheckBox(gridView.CurrentContext, gridView.StringLocalizer) { Name = $"jjchk_{index}", - Value = gridView.EncryptionService.EncryptStringWithUrlEscape(pkValues), + Value = gridView.EncryptionService.EncryptString(pkValues), Text = string.Empty, Attributes = { @@ -520,7 +522,7 @@ private async ValueTask GetMultiSelectCheckbox(Dictionary x.Any(kvp => kvp.Value.Equals(pkValues))); - if (OnRenderSelectedCellAsync is null) + if (OnRenderSelectedCell is null) return checkBox; var args = new GridSelectedCellEventArgs @@ -529,12 +531,12 @@ private async ValueTask GetMultiSelectCheckbox(Dictionary GetOnClickScript(FormStateData formStateData, BasicAction? defaultAction) + private string GetOnClickScript(FormStateData formStateData, BasicAction? defaultAction) { if (gridView.EnableEditMode || defaultAction == null) return string.Empty; @@ -543,10 +545,10 @@ private async ValueTask GetOnClickScript(FormStateData formStateData, Ba var actionButton = factory.CreateGridTableButton(defaultAction, gridView, formStateData); - if (OnRenderActionAsync != null) + if (OnRenderAction != null) { var args = new ActionEventArgs(defaultAction, actionButton, formStateData.Values); - await OnRenderActionAsync(gridView, args); + OnRenderAction(gridView, args); if (args.HtmlResult != null) actionButton = null; @@ -555,11 +557,10 @@ private async ValueTask GetOnClickScript(FormStateData formStateData, Ba if (actionButton is { Visible: true }) { if (!string.IsNullOrEmpty(actionButton.OnClientClick)) - return actionButton.OnClientClick!; + return actionButton.OnClientClick; - return !string.IsNullOrEmpty(actionButton.UrlAction) - ? $"window.location.href = '{actionButton.UrlAction}'" - : string.Empty; + if (!string.IsNullOrEmpty(actionButton.UrlAction)) + return $"window.location.href = '{actionButton.UrlAction}'"; } return string.Empty; @@ -580,4 +581,4 @@ private async ValueTask GetOnClickScript(FormStateData formStateData, Ba return gridView.FormValuesService.GetFormValuesWithMergedValuesAsync(gridView.FormElement, new FormStateData(row, gridView.UserValues, PageState.List), autoReloadFormFields, prefixName); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/GridTableHeader.cs b/src/MasterData.Core/UI/Components/GridView/GridTableHeader.cs index d4a5e955a..82f41e5ec 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridTableHeader.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridTableHeader.cs @@ -1,33 +1,37 @@ +#nullable disable warnings using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Data.Entity.Models; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Html; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; -internal sealed class GridTableHeader(JJGridView gridView) +internal sealed class GridTableHeader( + JJGridView gridView, + List visibleFields, + Dictionary filters) { private readonly IStringLocalizer _stringLocalizer = gridView.StringLocalizer; - public async Task GetHtmlBuilderAsync() + public HtmlBuilder GetHtmlBuilder() { var html = new HtmlBuilder(HtmlTag.Thead); if (gridView.DataSource?.Count == 0 && !gridView.ShowHeaderWhenEmpty) return html; - var visibleFieldsThList = await GetVisibleFieldsThList(); + var visibleFieldsThList = GetVisibleFieldsThList(); var tr = new HtmlBuilder(HtmlTag.Tr); + + if (gridView.EnableMultiSelect) + tr.Append(GetMultSelectThHtmlElement()); - tr.AppendIf(gridView.EnableMultiSelect, GetMultSelectThHtmlElement); tr.AppendRange(visibleFieldsThList); tr.AppendRange(GetActionsThList()); @@ -55,12 +59,11 @@ private IEnumerable GetActionsThList() } } - private async Task> GetVisibleFieldsThList() + private List GetVisibleFieldsThList() { var thList = new List(); var hasIcon = false; - - foreach (var field in await gridView.GetVisibleFieldsAsync()) + foreach (var field in visibleFields) { var th = new HtmlBuilder(HtmlTag.Th); var style = GetThStyle(field); @@ -106,7 +109,7 @@ private async Task> GetVisibleFieldsThList() if (string.IsNullOrWhiteSpace(order)) break; - if (order.StartsWith("[")) + if (order.StartsWith('[')) { order = order.Replace("[", ""); order = order.Replace("]", ""); @@ -138,9 +141,7 @@ private async Task> GetVisibleFieldsThList() } } - var currentFilter = await gridView.GetCurrentFilterAsync(); - - if (IsAppliedFilter(field, currentFilter)) + if (IsAppliedFilter(field)) { hasIcon = true; th.AppendComponent(new JJIcon("fa fa-filter text-info") @@ -160,21 +161,25 @@ private async Task> GetVisibleFieldsThList() return thList; } - private static bool IsAppliedFilter(ElementField field, Dictionary currentFilter) + private bool IsAppliedFilter(ElementField field) { if (field.Filter.Type is FilterMode.None) return false; - var hasFieldOrFromKey = currentFilter.ContainsKey(field.Name) || currentFilter.ContainsKey($"{field.Name}_from"); + var hasFieldOrFromKey = filters.ContainsKey(field.Name) || filters.ContainsKey($"{field.Name}_from"); return hasFieldOrFromKey; } - private HtmlBuilder GetAscendingIcon() => new JJIcon("fa fa-sort-amount-asc text-info").GetHtmlBuilder() - .WithToolTip(_stringLocalizer["Ascending order"]); + private JJIcon GetAscendingIcon() => new("fa fa-sort-amount-asc text-info") + { + Tooltip = _stringLocalizer["Ascending order"] + }; - private HtmlBuilder GetDescendingIcon() => new JJIcon("fa fa-sort-amount-desc text-info").GetHtmlBuilder() - .WithToolTip(_stringLocalizer["Descending order"]); + private JJIcon GetDescendingIcon() => new("fa fa-sort-amount-desc text-info") + { + Tooltip = _stringLocalizer["Descending order"] + }; private static string GetThStyle(FormElementField field) { @@ -202,7 +207,6 @@ private static string GetThStyle(FormElementField field) break; } case FormComponent.CheckBox: - return "text-align:center;"; case FormComponent.Icon: return "text-align:center;"; default: @@ -224,16 +228,7 @@ private HtmlBuilder GetMultSelectThHtmlElement() { var th = new HtmlBuilder(HtmlTag.Th); - var hasPages = true; - if (!gridView.IsPagingEnabled()) - { - hasPages = false; - } - else - { - if (gridView.TotalOfPages <= 1) - hasPages = false; - } + var hasPages = gridView.IsPagingEnabled() && gridView.TotalOfPages > 1; th.WithCssClass("jj-checkbox") .Append(HtmlTag.Input, input => @@ -288,4 +283,4 @@ private HtmlBuilder GetMultSelectThHtmlElement() return th; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/GridToolbar.cs b/src/MasterData.Core/UI/Components/GridView/GridToolbar.cs index e45f1f8df..f392eadf1 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridToolbar.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridToolbar.cs @@ -1,11 +1,11 @@ +using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Components; using JJConsulting.Html.Extensions; -using JJMasterData.Commons.Tasks; using JJMasterData.Core.DataDictionary.Models.Actions; +using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.UI.Events.Args; @@ -13,25 +13,24 @@ namespace JJMasterData.Core.UI.Components; internal sealed class GridToolbar(JJGridView gridView) { - internal event AsyncEventHandler OnRenderToolbarActionAsync; + internal event EventHandler? OnRenderToolbarAction; - public async ValueTask GetHtmlBuilderAsync() + public HtmlBuilder GetHtmlBuilder(FormStateData formStateData) { var toolbar = new JJToolbar(); - await AddActionsToToolbar(toolbar); + AddActionsToToolbar(toolbar, formStateData); return toolbar.GetHtmlBuilder().WithCssClass("mb-1"); } - private async ValueTask AddActionsToToolbar(JJToolbar toolbar) + private void AddActionsToToolbar(JJToolbar toolbar, FormStateData formStateData) { var actions = gridView .ToolbarActions .OrderBy(a => a.Order); var actionButtonFactory = gridView.ComponentFactory.ActionButton; - var formStateData = await gridView.GetFormStateDataAsync(); var groupedActions = new List(); @@ -65,10 +64,10 @@ private async ValueTask AddActionsToToolbar(JJToolbar toolbar) break; } - if (OnRenderToolbarActionAsync is not null) + if (OnRenderToolbarAction is not null) { var args = new GridToolbarActionEventArgs(action, linkButton); - await OnRenderToolbarActionAsync(gridView, args); + OnRenderToolbarAction(gridView, args); if (args.HtmlResult is not null) { @@ -96,4 +95,4 @@ private async ValueTask AddActionsToToolbar(JJToolbar toolbar) toolbar.Items.Add(groupedAction.GetHtmlBuilder()); } } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/GridViewFactory.cs b/src/MasterData.Core/UI/Components/GridView/GridViewFactory.cs index 90d76dc9b..4295d27d0 100644 --- a/src/MasterData.Core/UI/Components/GridView/GridViewFactory.cs +++ b/src/MasterData.Core/UI/Components/GridView/GridViewFactory.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System.Collections.Generic; using System.Data; using System.Threading.Tasks; @@ -8,14 +9,14 @@ using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; +using JJMasterData.Core.Html.Templates; using JJMasterData.Core.UI.Events.Abstractions; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; namespace JJMasterData.Core.UI.Components; -internal sealed class GridViewFactory(IHttpContext currentContext, +internal sealed class GridViewFactory(IHttpContextAccessor currentContext, IEntityRepository entityRepository, IDataDictionaryRepository dataDictionaryRepository, IEncryptionService encryptionService, @@ -28,7 +29,7 @@ internal sealed class GridViewFactory(IHttpContext currentContext, IStringLocalizer stringLocalizer, IGridEventHandlerResolver gridEventHandlerResolver, UrlRedirectService urlRedirectService, - HtmlTemplateService htmlTemplateService, + HtmlTemplateRenderer htmlTemplateRenderer, ILoggerFactory loggerFactory, IComponentFactory componentFactory) : IFormElementComponentFactory @@ -48,7 +49,7 @@ public JJGridView Create(FormElement formElement) fieldValidationService, stringLocalizer, urlRedirectService, - htmlTemplateService, + htmlTemplateRenderer, loggerFactory.CreateLogger(), componentFactory); @@ -65,12 +66,12 @@ public JJGridView Create(FormElement formElement) private static void SetGridEvents(JJGridView gridView, IGridEventHandler eventHandler) { gridView.OnDataLoadAsync += eventHandler.OnDataLoadAsync; - gridView.OnRenderActionAsync += eventHandler.OnRenderActionAsync; - gridView.OnRenderToolbarActionAsync += eventHandler.OnRenderToolbarActionAsync; - gridView.OnRenderCellAsync += eventHandler.OnRenderCellAsync; + gridView.OnRenderAction += eventHandler.OnRenderAction; + gridView.OnRenderToolbarAction += eventHandler.OnRenderToolbarAction; + gridView.OnRenderCell += eventHandler.OnRenderCell; gridView.OnFilterLoadAsync += eventHandler.OnFilterLoadAsync; - gridView.OnRenderSelectedCellAsync += eventHandler.OnRenderSelectedCellAsync; - gridView.OnRenderRowAsync += eventHandler.OnRenderRowAsync; + gridView.OnRenderSelectedCell += eventHandler.OnRenderSelectedCell; + gridView.OnRenderRow += eventHandler.OnRenderRow; } public JJGridView Create(DataTable dataTable) @@ -114,7 +115,7 @@ internal void SetGridUiOptions(JJGridView grid, GridUI gridOptions) { GridSettings settings = null; if (grid.MaintainValuesOnLoad) - settings = currentContext.Session.GetSessionValue($"jjcurrentui_{grid.FormElement.Name}"); + settings = currentContext.HttpContext!.GetGridSettingsCookie(grid.FormElement.Name); if (settings == null) { @@ -134,4 +135,4 @@ internal void SetGridUiOptions(JJGridView grid, GridUI gridOptions) grid.ShowHeaderWhenEmpty = gridOptions.ShowHeaderWhenEmpty; grid.EmptyDataText = gridOptions.EmptyDataText; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/GridView/JJGridView.cs b/src/MasterData.Core/UI/Components/GridView/JJGridView.cs index c45c14aab..f6376a33d 100644 --- a/src/MasterData.Core/UI/Components/GridView/JJGridView.cs +++ b/src/MasterData.Core/UI/Components/GridView/JJGridView.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.Data; using System.Linq; @@ -21,7 +19,6 @@ using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Commons.Tasks; using JJMasterData.Commons.Util; -using JJMasterData.Core.DataDictionary; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; using JJMasterData.Core.DataManager; @@ -29,9 +26,7 @@ using JJMasterData.Core.DataManager.Expressions; using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; +using JJMasterData.Core.Html.Templates; using JJMasterData.Core.Logging; using JJMasterData.Core.UI.Events; using JJMasterData.Core.UI.Events.Args; @@ -59,13 +54,13 @@ public class JJGridView : AsyncComponent #region Events - public event AsyncEventHandler? OnRenderCellAsync; + public event EventHandler? OnRenderCell; /// /// Event fired when rendering the checkbox used to select the Grid row. /// Fired only when EnableMultiSelect property is enabled. /// - public event AsyncEventHandler? OnRenderSelectedCellAsync; + public event EventHandler? OnRenderSelectedCell; /// /// Event fired to retrieve table data /// @@ -77,12 +72,12 @@ public class JJGridView : AsyncComponent /// using the proc informed in the FormElement; /// public event GridDataLoadEventHandler? OnDataLoadAsync; - public event AsyncEventHandler? OnRenderActionAsync; + public event EventHandler? OnRenderAction; public event AsyncEventHandler? OnFilterLoadAsync; - public event AsyncEventHandler? OnRenderToolbarActionAsync; + public event EventHandler? OnRenderToolbarAction; public event AsyncEventHandler? OnBeforeTableRenderAsync; public event AsyncEventHandler? OnAfterTableRenderAsync; - public event AsyncEventHandler? OnRenderRowAsync; + public event EventHandler? OnRenderRow; #endregion #region Properties @@ -95,7 +90,6 @@ public class JJGridView : AsyncComponent private GridSettingsForm? _gridSettingsForm; private ExportOptions? _currentExportConfig; private GridFilter? _filter; - private GridTable? _table; private List>? _dataSource; private List? _pkFields; private Dictionary? _defaultValues; @@ -105,7 +99,6 @@ public class JJGridView : AsyncComponent private JJDataImportation? _dataImportation; private JJDataExportation? _dataExportation; private GridScripts? _gridScripts; - private GridToolbar? _toolbar; private readonly FieldValidationService _fieldValidationService; private readonly UrlRedirectService _urlRedirectService; @@ -142,7 +135,7 @@ public JJDataExportation DataExportation _dataExportation.ShowRowStriped = CurrentSettings.ShowRowStriped; _dataExportation.UserValues = UserValues; _dataExportation.ProcessOptions = ExportAction.ProcessOptions; - _dataExportation.OnRenderCellAsync += OnRenderCellAsync; + _dataExportation.OnRenderCell += OnRenderCell; return _dataExportation; } @@ -239,11 +232,11 @@ public OrderByData CurrentOrder if (_currentOrder != null) return _currentOrder; - if (!CurrentContext.Request.Form.ContainsFormValues()) + if (!CurrentContext.HttpContext!.Request.HasFormContentType) { if (MaintainValuesOnLoad) { - var tableOrder = CurrentContext.Session[$"jj-grid-view-order-{Name}"]; + var tableOrder = CurrentContext.HttpContext!.GetGridOrderCookie(Name); if (tableOrder != null) { _currentOrder = OrderByData.FromString(tableOrder); @@ -252,10 +245,11 @@ public OrderByData CurrentOrder } else { - _currentOrder = OrderByData.FromString(CurrentContext.Request[$"grid-view-order-{Name}"]); + var order = CurrentContext.HttpContext!.Request.GetFormValue($"grid-view-order-{Name}"); + _currentOrder = OrderByData.FromString(order); if (_currentOrder == null) { - var tableOrder = CurrentContext.Session[$"jj-grid-view-order-{Name}"]; + var tableOrder = CurrentContext.HttpContext!.GetGridOrderCookie(Name); if (tableOrder != null) { _currentOrder = OrderByData.FromString(tableOrder); @@ -272,7 +266,9 @@ public OrderByData CurrentOrder } set { - CurrentContext.Session[$"jj-grid-view-order-{Name}"] = value.ToQueryParameter(); + if (MaintainValuesOnLoad) + CurrentContext.HttpContext!.SetGridOrderCookie(Name, value.ToQueryParameter()); + _currentOrder = value; } } @@ -286,11 +282,11 @@ public int CurrentPage return _currentPage; } - if (CurrentContext.Request.Form.ContainsFormValues()) + if (CurrentContext.HttpContext!.Request.HasFormContentType) { var currentPage = 1; var tablePageId = $"grid-view-page-{Name}"; - if (CurrentContext.Request.Form.TryGetValue(tablePageId, out var pageString)) + if (CurrentContext.HttpContext!.Request.Form.TryGetValue(tablePageId, out var pageString)) { if (int.TryParse(pageString, out var page)) currentPage = page; @@ -318,23 +314,13 @@ public int CurrentPage set { if (MaintainValuesOnLoad && PaginationType is GridPaginationType.Buttons) - CurrentContext.Session[$"jjcurrentpage_{Name}"] = value.ToString(); + CurrentContext.HttpContext!.SetGridCurrentPageCookie(Name, value); _currentPage = value; } } - private int GetPageFromPreferences() - { - var tablePage = CurrentContext.Session[$"jjcurrentpage_{Name}"]; - if (tablePage != null) - { - if (int.TryParse(tablePage, out var page)) - return page; - } - - return 1; - } + private int GetPageFromPreferences() => CurrentContext.HttpContext!.GetGridCurrentPageCookie(Name) ?? 1; public int TotalOfPages { @@ -369,7 +355,7 @@ public GridSettings CurrentSettings } if (MaintainValuesOnLoad) - CurrentSettings = CurrentContext.Session.GetSessionValue($"jjcurrentui_{FormElement.Name}"); + CurrentSettings = CurrentContext.HttpContext!.GetGridSettingsCookie(FormElement.Name); if (_currentSettings == null) CurrentSettings = GridSettingsForm.LoadFromForm(); @@ -379,7 +365,7 @@ public GridSettings CurrentSettings set { if (MaintainValuesOnLoad) - CurrentContext.Session.SetSessionValue($"jjcurrentui_{FormElement.Name}", value); + CurrentContext.HttpContext!.SetGridSettingsCookie(FormElement.Name, value); _currentSettings = value; } @@ -399,24 +385,6 @@ internal GridFilter Filter } } - internal GridTable Table - { - get - { - if (_table != null) - return _table; - - _table = new GridTable(this); - - _table.Body.OnRenderActionAsync += OnRenderActionAsync; - _table.Body.OnRenderCellAsync += OnRenderCellAsync; - _table.Body.OnRenderSelectedCellAsync += OnRenderSelectedCellAsync; - _table.Body.OnRenderRowAsync += OnRenderRowAsync; - - return _table; - } - } - public ExportOptions CurrentExportConfig { get @@ -425,9 +393,9 @@ public ExportOptions CurrentExportConfig return _currentExportConfig; _currentExportConfig = new ExportOptions(); - if (CurrentContext.Request.Form.ContainsFormValues()) + if (CurrentContext.HttpContext!.Request.HasFormContentType) { - _currentExportConfig = ExportOptions.LoadFromForm(CurrentContext.Request.Form, Name); + _currentExportConfig = ExportOptions.LoadFromForm(CurrentContext, Name); } return _currentExportConfig; @@ -445,12 +413,12 @@ public ExportOptions CurrentExportConfig public bool EnableMultiSelect { get; set; } /// - /// Keep the grid filters, order and pagination in the session, + /// Keep the grid filters, order and pagination in cookies, /// and recover on the first page load. (Default = false) /// /// /// When using this property, we recommend changing the object's [Name] parameter. - /// The [Name] property is used to compose the name of the session variable. + /// The [Name] property is used to compose the cookie names. /// public bool MaintainValuesOnLoad { get; set; } @@ -535,7 +503,7 @@ private ActionMap? CurrentActionMap { if (_currentActionMap != null || _isCustomCurrentActionMap) return _currentActionMap; - var encryptedActionMap = CurrentContext.Request.Form[$"grid-view-action-map-{Name}"]; + var encryptedActionMap = CurrentContext.HttpContext!.Request.GetFormValue($"grid-view-action-map-{Name}"); if (string.IsNullOrEmpty(encryptedActionMap)) return null; @@ -551,7 +519,7 @@ private ActionMap? CurrentActionMap private string? SelectedRowsId { - get => _selectedRowsId ??= CurrentContext.Request.Form[$"grid-view-selected-rows-{Name}"]; + get => _selectedRowsId ??= CurrentContext.HttpContext!.Request.GetFormValue($"grid-view-selected-rows-{Name}"); set => _selectedRowsId = value ?? ""; } @@ -562,7 +530,7 @@ protected RouteContext RouteContext if (_routeContext != null) return _routeContext; - var factory = new RouteContextFactory(CurrentContext.Request.QueryString, EncryptionService); + var factory = new RouteContextFactory(CurrentContext, EncryptionService); _routeContext = factory.Create(); return _routeContext; @@ -580,30 +548,15 @@ protected RouteContext RouteContext internal FieldValuesService FieldValuesService { get; } internal IStringLocalizer StringLocalizer { get; } - internal HtmlTemplateService HtmlTemplateService { get; } + internal HtmlTemplateRenderer HtmlTemplateRenderer { get; } internal IComponentFactory ComponentFactory { get; } internal IEntityRepository EntityRepository { get; } internal GridScripts Scripts => _gridScripts ??= new GridScripts(this); - internal IHttpContext CurrentContext { get; } + internal IHttpContextAccessor CurrentContext { get; } internal DataItemService DataItemService { get; } internal IEncryptionService EncryptionService { get; } - - private GridToolbar Toolbar - { - get - { - if (_toolbar is null) - { - _toolbar = new GridToolbar(this); - _toolbar.OnRenderToolbarActionAsync += OnRenderToolbarActionAsync; - } - - return _toolbar; - } - } - internal ILogger Logger { get; } internal FieldFormattingService FieldFormattingService { get; } @@ -613,7 +566,7 @@ private GridToolbar Toolbar internal JJGridView( FormElement formElement, - IHttpContext currentContext, + IHttpContextAccessor currentContext, IEntityRepository entityRepository, IEncryptionService encryptionService, DataItemService dataItemService, @@ -624,7 +577,7 @@ internal JJGridView( FieldValidationService fieldValidationService, IStringLocalizer stringLocalizer, UrlRedirectService urlRedirectService, - HtmlTemplateService htmlTemplateService, + HtmlTemplateRenderer htmlTemplateRenderer, ILogger logger, IComponentFactory componentFactory) { @@ -645,7 +598,7 @@ internal JJGridView( EncryptionService = encryptionService; StringLocalizer = stringLocalizer; _urlRedirectService = urlRedirectService; - HtmlTemplateService = htmlTemplateService; + HtmlTemplateRenderer = htmlTemplateRenderer; Logger = logger; ComponentFactory = componentFactory; EntityRepository = entityRepository; @@ -671,13 +624,14 @@ protected override async Task BuildResultAsync() return await GetExportationResult(); if (ComponentContext is ComponentContext.DownloadFile) - return ComponentFactory.Downloader.Create().GetDownloadResult(); + return await ComponentFactory.Downloader.Create().GetDownloadResultAsync(); if (ComponentContext is ComponentContext.GridViewRow) { - var rowIndex = int.Parse(CurrentContext.Request.QueryString["gridViewRowIndex"]); + var rowIndex = int.Parse(CurrentContext.HttpContext!.Request.Query["gridViewRowIndex"].ToString()); + var filters = await GetCurrentFilterAsync(); - await SetDataSource(); + await SetDataSource(filters); var htmlResponse = await GetTableRowHtmlAsync(rowIndex); @@ -686,11 +640,12 @@ protected override async Task BuildResultAsync() if (ComponentContext is ComponentContext.GridViewScrollPagination) { - await SetDataSource(); + var filters = await GetCurrentFilterAsync(); + await SetDataSource(filters); var htmlBuilder = new HtmlBuilder(); - - var rows = await Table.Body.GetRowsList(); + var visibleFields = await GetVisibleFieldsAsync(); + var rows = await CreateTableBody(visibleFields).GetRowsList(); htmlBuilder.AppendRange(rows); return new ContentComponentResult(htmlBuilder); @@ -712,8 +667,8 @@ protected override async Task BuildResultAsync() if (ComponentContext is ComponentContext.SearchBoxFilter) { - var fieldName = CurrentContext.Request.QueryString["fieldName"]; - var field = FormElement.Fields[fieldName]; + var fieldName = CurrentContext.HttpContext!.Request.Query["fieldName"]; + var field = FormElement.Fields[fieldName!]; var formStateData = new FormStateData(await GetCurrentFilterAsync(), UserValues, PageState.Filter); var jjSearchBox = ComponentFactory.Controls.Create(FormElement,field, formStateData, Name) as JJSearchBox; jjSearchBox!.Name = GridFilter.FilterFieldPrefix + jjSearchBox.Name; @@ -722,7 +677,7 @@ protected override async Task BuildResultAsync() if (ComponentContext is ComponentContext.UrlRedirect) { - return await _urlRedirectService.GetUrlRedirectResult(this,CurrentActionMap); + return await _urlRedirectService.GetUrlRedirectResult(this,CurrentActionMap!); } HtmlBuilder? sqlActionError = null; @@ -777,7 +732,7 @@ internal async Task GetHtmlBuilderAsync() } if (ShowToolbar) - div.Append(await GetToolbarHtmlBuilder()); + div.Append(await GetToolbarHtmlAsync()); div.Append(await GetTableHtmlBuilder()); @@ -809,8 +764,9 @@ private async Task GetTableHtmlBuilder() AssertProperties(); var html = new HtmlBuilder(HtmlTag.Div); + var filters = await GetCurrentFilterAsync(); - await SetDataSource(); + await SetDataSource(filters); var totalOfPages = TotalOfPages; @@ -822,7 +778,7 @@ private async Task GetTableHtmlBuilder() html.Append(sortConfig); } - html.AppendRange(GetHiddenInputs()); + html.AppendRange(GetHiddenInputs(filters)); if (CurrentPage <= 0 || (CurrentPage > totalOfPages && totalOfPages != 0)) { @@ -847,10 +803,10 @@ private async Task GetTableHtmlBuilder() }); html.Append(wrapper); } - html.Append(await Table.GetHtmlBuilder()); + html.Append(await GetGridTableHtmlBuilder(filters)); if (DataSource?.Count == 0 && !string.IsNullOrEmpty(EmptyDataText)) - html.Append(await GetNoRecordsAlert()); + html.Append(GetNoRecordsAlert(filters)); if (IsPagingEnabled() && PaginationType == GridPaginationType.Buttons) { @@ -873,6 +829,41 @@ private async Task GetTableHtmlBuilder() return html; } + + private GridToolbar CreateToolbar() + { + var toolbar = new GridToolbar(this); + toolbar.OnRenderToolbarAction += OnRenderToolbarAction; + + return toolbar; + } + + private async ValueTask GetGridTableHtmlBuilder(Dictionary filters) + { + var visibleFields = await GetVisibleFieldsAsync(); + + var table = new GridTable(this, visibleFields, filters); + + ConfigureTableBody(table.Body); + + return await table.GetHtmlBuilderAsync(); + } + + private GridTableBody CreateTableBody(List visibleFields) + { + var body = new GridTableBody(this, visibleFields); + ConfigureTableBody(body); + + return body; + } + + private void ConfigureTableBody(GridTableBody body) + { + body.OnRenderAction += OnRenderAction; + body.OnRenderCell += OnRenderCell; + body.OnRenderSelectedCell += OnRenderSelectedCell; + body.OnRenderRow += OnRenderRow; + } public GridPaginationType PaginationType => FormElement.Options.Grid.PaginationType; @@ -893,25 +884,33 @@ private JJAlert GetPaginationWarningAlert(int totalPages) }; } - private IEnumerable GetHiddenInputs() + private List GetHiddenInputs(Dictionary filters) { - yield return new HtmlBuilder().AppendHiddenInput($"grid-view-order-{Name}", CurrentOrder.ToQueryParameter()); - yield return new HtmlBuilder().AppendHiddenInput($"grid-view-page-{Name}", CurrentPage.ToString()); - yield return new HtmlBuilder().AppendHiddenInput($"grid-view-action-map-{Name}", EncryptionService.EncryptObject(CurrentActionMap) ?? string.Empty); - yield return new HtmlBuilder().AppendHiddenInput($"grid-view-row-{Name}", string.Empty); + var hiddenInputs = new List + { + new HtmlBuilder().AppendHiddenInput($"grid-view-order-{Name}", CurrentOrder.ToQueryParameter()), + new HtmlBuilder().AppendHiddenInput($"grid-view-page-{Name}", CurrentPage.ToString()), + new HtmlBuilder().AppendHiddenInput($"grid-view-action-map-{Name}", EncryptionService.EncryptObject(CurrentActionMap) ?? string.Empty), + new HtmlBuilder().AppendHiddenInput($"grid-view-row-{Name}", string.Empty), + new HtmlBuilder().AppendHiddenInput($"grid-view-filters-{Name}", EncryptionService.EncryptObject(filters) ?? string.Empty) + }; if (EnableMultiSelect) { - yield return new HtmlBuilder().AppendHiddenInput($"grid-view-selected-rows-{Name}", SelectedRowsId ?? string.Empty); + hiddenInputs.Add(new HtmlBuilder().AppendHiddenInput($"grid-view-selected-rows-{Name}", SelectedRowsId ?? string.Empty)); } + + return hiddenInputs; } private async Task GetTableRowHtmlAsync(int rowIndex) { var row = DataSource?[rowIndex]; + var visibleFields = await GetVisibleFieldsAsync(); string result = string.Empty; - foreach (var td in await Table.Body.GetTdHtmlList(row ?? new Dictionary(), rowIndex)) + foreach (var td in await CreateTableBody(visibleFields) + .GetTdHtmlList(row ?? new Dictionary(), rowIndex)) result += td; return result; @@ -927,11 +926,16 @@ internal JJTitle GetTitle() return ComponentFactory.Title.Create(FormElement, new FormStateData(RelationValues!,UserValues, PageState.List), TitleActions); } - internal ValueTask GetToolbarHtmlBuilder() => Toolbar.GetHtmlBuilderAsync(); + internal HtmlBuilder GetToolbarHtmlBuilder(FormStateData formStateData) => + CreateToolbar().GetHtmlBuilder(formStateData); public ValueTask GetFilterHtmlAsync() => Filter.GetFilterHtml(); - public ValueTask GetToolbarHtmlAsync() => GetToolbarHtmlBuilder(); + public async ValueTask GetToolbarHtmlAsync() + { + var formStateData = await GetFormStateDataAsync(); + return GetToolbarHtmlBuilder(formStateData); + } private Task GetSortingConfigAsync() => new GridSortingConfig(this).GetHtmlBuilderAsync(); @@ -942,7 +946,7 @@ private Task ExecuteSqlCommand(SqlCommandAction? action) var gridSqlAction = new GridSqlCommandAction(this); - return gridSqlAction.ExecuteSqlCommand(CurrentActionMap, action); + return gridSqlAction.ExecuteSqlCommand(CurrentActionMap!, action); } private void AssertProperties() @@ -955,7 +959,7 @@ private void AssertProperties() "It is not allowed to enable multiple selection without defining a primary key in the data dictionary"); } - private async Task GetNoRecordsAlert() + private HtmlBuilder GetNoRecordsAlert(Dictionary filters) { var alert = new JJAlert { @@ -965,7 +969,7 @@ private async Task GetNoRecordsAlert() Icon = FontAwesomeIcon.InfoCircle }; - var hasFilter = await Filter.HasFilter(); + var hasFilter = Filter.HasFilter(filters); if (!hasFilter) return alert.GetHtmlBuilder(); @@ -1013,18 +1017,22 @@ private async Task GetSettingsHtml() Title = StringLocalizer["Configure Grid"] }; - var btnOk = new JJLinkButton(); - btnOk.Text = StringLocalizer["Ok"]; - btnOk.IconClass = "fa fa-check"; - btnOk.ShowAsButton = true; - btnOk.OnClientClick = Scripts.GetGridSettingsScript(ConfigAction, RelationValues); + var btnOk = new JJLinkButton + { + Text = StringLocalizer["Ok"], + IconClass = "fa fa-check", + ShowAsButton = true, + OnClientClick = Scripts.GetGridSettingsScript(ConfigAction, RelationValues) + }; modal.Buttons.Add(btnOk); - var btnCancel = new JJLinkButton(); - btnCancel.Text = StringLocalizer["Cancel"]; - btnCancel.IconClass = "fa fa-times"; - btnCancel.ShowAsButton = true; - btnCancel.OnClientClick = Scripts.GetCloseConfigUIScript(); + var btnCancel = new JJLinkButton + { + Text = StringLocalizer["Cancel"], + IconClass = "fa fa-times", + ShowAsButton = true, + OnClientClick = Scripts.GetCloseConfigUIScript() + }; modal.Buttons.Add(btnCancel); modal.Content = GridSettingsForm.GetHtmlBuilder(CanCustomPaging(), CurrentSettings); @@ -1071,7 +1079,7 @@ private async Task GetCaptionHtml() if (!isVisible) return new HtmlBuilder(string.Empty); - var captionView = new GridCaptionView(action.Tooltip,ComponentFactory.Controls.ComboBox, StringLocalizer) + var captionView = new GridCaptionView(action.Tooltip!,ComponentFactory.Controls.ComboBox, StringLocalizer) { Name = Name, ShowAsModal = true, @@ -1107,12 +1115,12 @@ internal string GetFieldName(string fieldName, Dictionary row) public Dictionary GetSelectedRowId() { var values = new Dictionary(); - string currentRow = CurrentContext.Request[$"grid-view-row-{Name}"]; + var currentRowValue = CurrentContext.HttpContext!.Request.GetFormValue($"grid-view-row-{Name}"); - if (string.IsNullOrEmpty(currentRow)) + if (string.IsNullOrEmpty(currentRowValue)) return values; - var decriptId = EncryptionService.DecryptStringWithUrlUnescape(currentRow); + var decriptId = EncryptionService.DecryptString(currentRowValue); var @params = HttpUtility.ParseQueryString(decriptId); foreach (string key in @params) @@ -1125,7 +1133,7 @@ public Dictionary GetSelectedRowId() private async Task GetExportationResult() { - string expressionType = CurrentContext.Request.QueryString["dataExportationOperation"]; + string expressionType = CurrentContext.HttpContext!.Request.Query["dataExportationOperation"].ToString(); switch (expressionType) { case "showOptions": @@ -1182,16 +1190,16 @@ public async ValueTask ExportFileInBackground() public async Task>?> GetDictionaryListAsync() { - await SetDataSource(); + var filters = await GetCurrentFilterAsync(); + await SetDataSource(filters); return DataSource; } - private async Task SetDataSource() + private async Task SetDataSource(Dictionary filters) { if (DataSource == null && !IsUserSetDataSource) { - var filters = await GetCurrentFilterAsync(); var result = await GetDataSourceAsync(new EntityParameters { Filters = filters, @@ -1207,7 +1215,7 @@ private async Task SetDataSource() CurrentPage = 1; result = await GetDataSourceAsync(new EntityParameters { - Filters = await GetCurrentFilterAsync(), + Filters = filters, OrderBy = CurrentOrder, RecordsPerPage = CurrentSettings.RecordsPerPage, CurrentPage = CurrentPage @@ -1321,7 +1329,7 @@ public List> GetSelectedGridValues() foreach (var pk in pkList) { var values = new Dictionary(); - var descriptval = EncryptionService.DecryptStringWithUrlUnescape(pk); + var descriptval = EncryptionService.DecryptString(pk); string[] ids = descriptval.Split(';'); for (var i = 0; i < pkFields.Count; i++) { @@ -1340,7 +1348,7 @@ public void ClearSelectedGridValues() SelectedRowsId = string.Empty; } - internal async Task GetEncryptedSelectedRowsAsync() + private async Task GetEncryptedSelectedRowsAsync() { var result = await GetDataSourceAsync(new EntityParameters { @@ -1359,7 +1367,7 @@ internal async Task GetEncryptedSelectedRowsAsync() selectedKeys.Append(','); string values = DataHelper.ParsePkValues(FormElement, row, ';'); - selectedKeys.Append((string?)EncryptionService.EncryptStringWithUrlEscape(values)); + selectedKeys.Append((string?)EncryptionService.EncryptString(values)); } return selectedKeys.ToString(); @@ -1537,7 +1545,10 @@ private static void ValidateAction(BasicAction action) public bool IsExportPost() { - return "startProcess".Equals(CurrentContext.Request["dataExportationOperation"]) && Name.Equals(CurrentContext.Request["gridViewName"]); + var request = CurrentContext.HttpContext!.Request.GetValue; + var operation = request("dataExportationOperation"); + var gridViewName = request("gridViewName"); + return "startProcess".Equals(operation) && Name.Equals(gridViewName); } public void SetUserValues(string key, string value) @@ -1558,4 +1569,4 @@ public ActionContext GetActionContext(BasicAction basicAction, FormStateData for ParentComponentName = Name }; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/IComponentFactory.cs b/src/MasterData.Core/UI/Components/IComponentFactory.cs index d8d087642..f1b9920f9 100644 --- a/src/MasterData.Core/UI/Components/IComponentFactory.cs +++ b/src/MasterData.Core/UI/Components/IComponentFactory.cs @@ -1,4 +1,3 @@ -#nullable enable using JJMasterData.Core.UI.Components.Factories; using JJMasterData.Core.UI.Routing; diff --git a/src/MasterData.Core/UI/Components/IO/FileDownloader/FileDownloaderFactory.cs b/src/MasterData.Core/UI/Components/IO/FileDownloader/FileDownloaderFactory.cs index 369165ecf..e64600376 100644 --- a/src/MasterData.Core/UI/Components/IO/FileDownloader/FileDownloaderFactory.cs +++ b/src/MasterData.Core/UI/Components/IO/FileDownloader/FileDownloaderFactory.cs @@ -1,19 +1,32 @@ +using System.Collections.Generic; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Core.Http.Abstractions; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; +using JJMasterData.Commons.Storage; +using JJMasterData.Core.DataDictionary.Models; namespace JJMasterData.Core.UI.Components; -public sealed class FileDownloaderFactory(IHttpContext httpContext, - IEncryptionService encryptionService, - IStringLocalizer stringLocalizer, - ILoggerFactory loggerFactory) +public sealed class FileDownloaderFactory(IHttpContextAccessor httpContext, + IFileStorage fileStorage, + IEncryptionService encryptionService) { public JJFileDownloader Create() { - return new JJFileDownloader(httpContext, encryptionService, stringLocalizer, - loggerFactory.CreateLogger()); + return new JJFileDownloader(httpContext, fileStorage, encryptionService); } - -} \ No newline at end of file + + public JJFileDownloader Create(string fullPath) + { + var downloader = Create(); + downloader.FullPath = fullPath; + return downloader; + } + + public JJFileDownloader Create(FormElement formElement, FormElementField field, Dictionary values, string fileName, bool isTemporary = false) + { + var folderPath = FileStoragePath.GetFolderPath(formElement, field, values); + var fullPath = FileStoragePath.Combine(folderPath, fileName); + + return Create(fullPath); + } +} diff --git a/src/MasterData.Core/UI/Components/IO/FileDownloader/JJFileDownloader.cs b/src/MasterData.Core/UI/Components/IO/FileDownloader/JJFileDownloader.cs index ef7347a29..40590aaea 100644 --- a/src/MasterData.Core/UI/Components/IO/FileDownloader/JJFileDownloader.cs +++ b/src/MasterData.Core/UI/Components/IO/FileDownloader/JJFileDownloader.cs @@ -1,178 +1,66 @@ -using System; +#nullable disable warnings +using System; using System.IO; +using System.Threading.Tasks; using System.Web; -using JJConsulting.Html; -using JJConsulting.Html.Bootstrap.Abstractions; -using JJConsulting.Html.Bootstrap.Components; -using JJConsulting.Html.Bootstrap.Extensions; -using JJConsulting.Html.Extensions; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Exceptions; -using JJMasterData.Commons.Extensions; using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Commons.Util; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; - using JJMasterData.Core.UI.Routing; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; namespace JJMasterData.Core.UI.Components; public class JJFileDownloader( - IHttpContext currentContext, - IEncryptionService encryptionService, - IStringLocalizer stringLocalizer, - ILogger logger) - : HtmlComponent + IHttpContextAccessor httpContextAccessor, + IFileStorage fileStorage, + IEncryptionService encryptionService) { - public const string DirectDownloadParameter = "directDownloadFilePath"; - public const string DownloadParameter = "downloadFilePath"; - - public string FilePath { get; set; } - public bool IsExternalLink { get; set; } + private const string FileTokenParameter = "downloadFileToken"; - internal IHttpContext CurrentContext { get; } = currentContext; - internal IStringLocalizer StringLocalizer { get; } = stringLocalizer; - internal ILogger Logger { get; } = logger; - internal IEncryptionService EncryptionService { get; } = encryptionService; + public string FullPath { get; set; } - - protected override HtmlBuilder BuildHtml() + public async Task GetDirectDownloadResultAsync() { - if (string.IsNullOrEmpty(FilePath)) - throw new JJMasterDataException(StringLocalizer["Invalid file path or badly formatted URL"]); - - if (IsExternalLink) - return GetDownloadHtmlElement(); - - GetDirectDownloadResult(); + if (string.IsNullOrEmpty(FullPath)) + throw new ArgumentNullException(nameof(FullPath)); - return null; + var stream = await fileStorage.OpenReadAsync(FullPath); + + var fileName = Path.GetFileName(FullPath); + + return new FileStreamComponentResult(stream, fileName); } - private HtmlBuilder GetDownloadHtmlElement() + public async Task GetDownloadResultAsync() { - var file = new FileInfo(FilePath); - string fileName = file.Name; - string size = Format.FormatFileSize(file.Length); - string lastWriteTime = file.LastWriteTime.ToDateTimeString(); - string url = CurrentContext.Request.AbsoluteUri.Replace(DirectDownloadParameter, DownloadParameter); - - var htmlTitle = new JJTitle - { - Title = StringLocalizer["Downloading"], - SubTitle = fileName.ToLower() - }; + var token = httpContextAccessor.HttpContext!.Request.Query[FileTokenParameter].ToString(); + if (string.IsNullOrEmpty(token)) + throw new JJMasterDataException("Invalid file token."); + + FullPath = encryptionService.DecryptString(token); - var html = HtmlBuilder.Div() - .AppendComponent(htmlTitle) - .AppendSection(section => - { - section.WithCssClass("container mt-3"); - section.AppendDiv(div => - { - div.WithCssClass("jumbotron px-3 py-4 px-sm-4 py-sm-5 bg-light rounded-3 mb-3"); - div.AppendDiv(div => - { - div.AppendH1(h1 => - { - h1.AppendComponent(new JJIcon("fa fa-cloud-download text-info")); - h1.AppendText(fileName); - }); - div.Append(HtmlTag.P,p => - { - p.AppendText($"{StringLocalizer["File Size:"]} {size}"); - p.Append(HtmlTag.Br); - p.AppendText($"{StringLocalizer["Last write time:"]} {lastWriteTime}"); - }); - div.AppendHr(hr => - { - hr.WithCssClass("my-4"); - }); - div.Append(HtmlTag.P, p => - { - p.AppendText(StringLocalizer["You are downloading file {0}.", fileName]); - p.AppendText(" "); - p.AppendText($"{StringLocalizer["If the download not start automatically"]}, "); - p.Append(HtmlTag.A, a => - { - a.WithAttribute("href", url); - a.AppendText(StringLocalizer["click here."]); - }); - }); - }); - }); - }); - return html; + return await GetDirectDownloadResultAsync(); } - - internal FileComponentResult GetDirectDownloadResult() - { - if (string.IsNullOrEmpty(FilePath)) - throw new ArgumentNullException(nameof(FilePath)); - - if (!File.Exists(FilePath)) - { - var exception = new JJMasterDataException(StringLocalizer["File {0} not found!", Path.GetFileName(FilePath)]); - Logger.LogError(exception, "File {FilePath} not found!", FilePath); - throw exception; - } - return new FileComponentResult(FilePath); - } - - public FileComponentResult GetDownloadResult() + public string GetDownloadUrl(string absoluteUri) { - bool isExternalLink = false; - string criptFilePath = CurrentContext.Request.QueryString[DownloadParameter]; - if (criptFilePath == null) - { - criptFilePath = CurrentContext.Request.QueryString[DirectDownloadParameter]; - isExternalLink = true; - } - - if (criptFilePath == null) - throw new JJMasterDataException("Invalid file path or badly formatted URL"); - - string filePath = EncryptionService.DecryptStringWithUrlUnescape(criptFilePath); + if (FullPath == null) + throw new ArgumentNullException(nameof(FullPath)); - FilePath = filePath ?? throw new JJMasterDataException("Invalid file path or badly formatted URL"); - IsExternalLink = isExternalLink; - - return GetDirectDownloadResult(); - } - - public string GetDownloadUrl() - { - var url = CurrentContext.Request.AbsoluteUri; - var encryptedFilePath = EncryptionService.EncryptStringWithUrlEscape(FilePath); - - var uriBuilder = new UriBuilder(url); + var uriBuilder = new UriBuilder(absoluteUri); var query = HttpUtility.ParseQueryString(uriBuilder.Query); - var routeContext = new RouteContext( ComponentContext.DownloadFile); - var encryptedRouteContext = EncryptionService.EncryptObject(routeContext); - - query["routeContext"] = encryptedRouteContext; - query[DirectDownloadParameter] = encryptedFilePath; + var routeContext = new RouteContext(ComponentContext.DownloadFile); + + query["routeContext"] = encryptionService.EncryptObject(routeContext); + query[FileTokenParameter] = encryptionService.EncryptString(FullPath); uriBuilder.Query = query.ToString()!; return uriBuilder.Uri.PathAndQuery; } - public static string GetExternalDownloadLink(IEncryptionService encryptionService, string absoluteUri, string filePath) + public string GetDownloadUrl() { - var uriBuilder = new UriBuilder(absoluteUri); - var query = HttpUtility.ParseQueryString(uriBuilder.Query); - var routeContext = new RouteContext( ComponentContext.DownloadFile); - var encryptedRouteContext = encryptionService.EncryptObject(routeContext); - var encryptedFilePath = encryptionService.EncryptStringWithUrlEscape(filePath); - query["routeContext"] = encryptedRouteContext; - query[DirectDownloadParameter] = encryptedFilePath; - - uriBuilder.Query = query.ToString()!; - - return uriBuilder.Uri.AbsoluteUri; + return GetDownloadUrl(httpContextAccessor.HttpContext!.Request.GetAbsoluteUri()); } -} +} \ No newline at end of file diff --git a/src/MasterData.Core/UI/Components/IO/UploadArea/JJUploadArea.cs b/src/MasterData.Core/UI/Components/IO/UploadArea/JJUploadArea.cs index 525c9b98f..a90df1173 100644 --- a/src/MasterData.Core/UI/Components/IO/UploadArea/JJUploadArea.cs +++ b/src/MasterData.Core/UI/Components/IO/UploadArea/JJUploadArea.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,23 +8,19 @@ using JJConsulting.Html.Extensions; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Commons.Tasks; -using JJMasterData.Core.DataManager.IO; -using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Events.Args; - using JJMasterData.Core.UI.Routing; +using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; namespace JJMasterData.Core.UI.Components; public class JJUploadArea : AsyncComponent { - private readonly IRequestLengthService _requestLengthService; - private readonly IHttpContext _httpContext ; - private readonly UploadAreaService _uploadAreaService ; + private readonly IOptions _requestLengthService; + private readonly IHttpContextAccessor _httpContext ; + private readonly UploadAreaManager _manager ; private readonly IStringLocalizer _stringLocalizer ; private readonly IEncryptionService _encryptionService; @@ -33,12 +28,20 @@ public class JJUploadArea : AsyncComponent /// /// Event fired when the file is posted. /// - public event EventHandler? OnFileUploaded; + public event EventHandler? OnFileUploaded + { + add => _manager.OnFileUploaded += value; + remove => _manager.OnFileUploaded -= value; + } /// /// Async event fired when the file is posted. /// - public event AsyncEventHandler? OnFileUploadedAsync; + public event AsyncEventHandler? OnFileUploadedAsync + { + add => _manager.OnFileUploadedAsync += value; + remove => _manager.OnFileUploadedAsync -= value; + } /// /// Allowed extension type, separated by comma. /// Default: * @@ -106,34 +109,32 @@ private string GetUploadAreaLabel() /// public int MaxFiles { get; set; } = int.MaxValue; - - private RouteContext? _routeContext; internal RouteContext RouteContext { get { - if (_routeContext != null) - return _routeContext; + if (field != null) + return field; - var factory = new RouteContextFactory(_httpContext.Request.QueryString, _encryptionService); - _routeContext = factory.Create(); + var factory = new RouteContextFactory(_httpContext, _encryptionService); + field = factory.Create(); - return _routeContext; + return field; } } public JJUploadArea( - IHttpContext httpContext, - UploadAreaService uploadAreaService, + IHttpContextAccessor httpContext, + UploadAreaManager manager, IEncryptionService encryptionService, - IRequestLengthService requestLengthService, + IOptions requestLengthService, IStringLocalizer stringLocalizer) { _requestLengthService = requestLengthService; Name = "upload-area"; _httpContext = httpContext; - _uploadAreaService = uploadAreaService; + _manager = manager; _stringLocalizer = stringLocalizer; _encryptionService = encryptionService; MaxFileSize = _requestLengthService.GetMaxRequestBodySize(); @@ -141,21 +142,15 @@ public JJUploadArea( protected override async Task BuildResultAsync() { - if (_uploadAreaService.TryGetFile(Multiple ? "uploadAreaFile[0]" : "uploadAreaFile", out var formFile)) + if (_manager.TryGetFile(Multiple ? "uploadAreaFile[0]" : "uploadAreaFile", out var formFile)) return await GetFileUploadResultAsync(formFile!); return new RenderedComponentResult(GetUploadAreaHtmlBuilder()); } - public async Task GetFileUploadResultAsync(FormFileContent formFile) + public async Task GetFileUploadResultAsync(IFormFile formFile) { - if (OnFileUploaded != null) - _uploadAreaService.OnFileUploaded += OnFileUploaded; - - if (OnFileUploadedAsync != null) - _uploadAreaService.OnFileUploadedAsync += OnFileUploadedAsync; - - var dto = await _uploadAreaService.UploadFileAsync(formFile, AllowedTypes); + var dto = await _manager.UploadFileAsync(formFile, AllowedTypes); var result = new JsonComponentResult(dto); @@ -210,7 +205,7 @@ private string GetAllowedTypes() if(allowedTypes.Length > 0) allowedTypes.Append(','); - if (type.Trim().StartsWith(".")) + if (type.Trim().StartsWith('.')) allowedTypes.Append(type); else diff --git a/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaFactory.cs b/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaFactory.cs index c729373d8..6bef6be05 100644 --- a/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaFactory.cs +++ b/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaFactory.cs @@ -1,19 +1,19 @@ using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Core.DataManager.Services; -using JJMasterData.Core.Http.Abstractions; +using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; namespace JJMasterData.Core.UI.Components; -public sealed class UploadAreaFactory(IHttpContext httpContext, - UploadAreaService uploadAreaService, +public sealed class UploadAreaFactory(IHttpContextAccessor httpContext, + UploadAreaManager uploadAreaManager, IEncryptionService encryptionService, - IRequestLengthService requestLengthService, + IOptions requestLengthService, IStringLocalizer stringLocalizer) { public JJUploadArea Create() { - return new JJUploadArea(httpContext,uploadAreaService,encryptionService,requestLengthService, stringLocalizer); + return new JJUploadArea(httpContext,uploadAreaManager,encryptionService,requestLengthService, stringLocalizer); } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaManager.cs b/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaManager.cs new file mode 100644 index 000000000..3e8dc2eea --- /dev/null +++ b/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaManager.cs @@ -0,0 +1,64 @@ +using System; +using System.Threading.Tasks; +using JJMasterData.Commons.Exceptions; +using JJMasterData.Commons.Tasks; +using JJMasterData.Core.DataManager.Services; +using JJMasterData.Core.UI.Events.Args; + +namespace JJMasterData.Core.UI.Components; + +public class UploadAreaManager(IHttpContextAccessor httpContextAccessor, FileValidationService fileValidationService) +{ + public event EventHandler? OnFileUploaded; + public event AsyncEventHandler? OnFileUploadedAsync; + + public async Task UploadFileAsync(IFormFile file, string? allowedTypes = null) + { + UploadAreaResultDto dto = new(); + + try + { + var message = string.Empty; + + fileValidationService.Validate(file, allowedTypes); + + var args = new FormUploadFileEventArgs(file); + OnFileUploaded?.Invoke(this, args); + + if (OnFileUploadedAsync != null) + await OnFileUploadedAsync.Invoke(this, args); + + fileValidationService.Validate(args.File, allowedTypes); + + var errorMessage = args.ErrorMessage; + if (args.SuccessMessage != null) + message = args.SuccessMessage; + + if (!string.IsNullOrEmpty(errorMessage)) + { + dto.ErrorMessage = errorMessage; + return dto; + } + + dto.SuccessMessage = message; + } + catch (JJMasterDataException ex) + { + dto.ErrorMessage = ex.Message; + } + + return dto; + } + + public bool TryGetFile(string fileName, out IFormFile? formFile) + { + if (httpContextAccessor.HttpContext?.Request.HasFormContentType is false) + { + formFile = null; + return false; + } + + formFile = httpContextAccessor.HttpContext?.Request.Form.Files[fileName]; + return formFile != null; + } +} diff --git a/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaResultDto.cs b/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaResultDto.cs index 85948a739..6d63cdc91 100644 --- a/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaResultDto.cs +++ b/src/MasterData.Core/UI/Components/IO/UploadArea/UploadAreaResultDto.cs @@ -1,6 +1,3 @@ -#nullable enable - - using System.Text.Json.Serialization; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/IO/UploadView/JJUploadView.cs b/src/MasterData.Core/UI/Components/IO/UploadView/JJUploadView.cs index 12f717752..a64b6e380 100644 --- a/src/MasterData.Core/UI/Components/IO/UploadView/JJUploadView.cs +++ b/src/MasterData.Core/UI/Components/IO/UploadView/JJUploadView.cs @@ -1,6 +1,6 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; -using System.Data; using System.Globalization; using System.IO; using System.Linq; @@ -12,22 +12,20 @@ using JJConsulting.Html.Bootstrap.Extensions; using JJConsulting.Html.Bootstrap.Models; using JJConsulting.Html.Extensions; +using JJConsulting.MasterData.Storage.Abstractions; using JJMasterData.Commons.Exceptions; -using JJMasterData.Commons.Extensions; using JJMasterData.Commons.Security.Cryptography.Abstractions; +using JJMasterData.Commons.Storage; +using JJMasterData.Commons.Tasks; using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.DataManager.IO; -using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Http.Abstractions; -using JJMasterData.Core.Tasks; using JJMasterData.Core.UI.Events.Args; - using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; +// ReSharper disable MemberCanBePrivate.Global namespace JJMasterData.Core.UI.Components; /// @@ -40,291 +38,214 @@ namespace JJMasterData.Core.UI.Components; /// public class JJUploadView : AsyncComponent { - private const string FileName = "Name"; private const string FileNameJs = "NameJS"; - private const string Size = "Size"; - private const string LastWriteTime = "LastWriteTime"; - - private UrlRedirectAction _downloadAction; - private ScriptAction _deleteAction; - private ScriptAction _renameAction; - private JJGridView _gridView; - private JJUploadArea _uploadArea; - private FormFileManager _formFileManager; - private UploadViewScripts _scripts; - private RouteContext _routeContext; + private const string FileNameField = "Name"; + private const string FileSizeField = "Size"; + private const string LastModifiedField = "LastModified"; + private const string FullPathField = "FullPath"; + private const string FolderPathField = "FolderPath"; + + internal const string DownloadFileActionName = "download-file"; + internal const string DeleteFileActionName = "delete-file"; + internal const string RenameFileActionName = "rename-file"; + + internal const string TempPathFolder = "{app.path}/MasterDataDraftFiles/"; - public event EventHandler OnBeforeCreateFile; - public event EventHandler OnBeforeDeleteFile; - public event EventHandler OnBeforeRenameFile; + public event AsyncEventHandler OnBeforeCreateFileAsync + { + add => Manager.OnBeforeCreateFileAsync += value; + remove => Manager.OnBeforeCreateFileAsync -= value; + } + + public event AsyncEventHandler OnBeforeDeleteFileAsync + { + add => Manager.OnBeforeDeleteFileAsync += value; + remove => Manager.OnBeforeDeleteFileAsync -= value; + } + + public event AsyncEventHandler OnBeforeRenameFileAsync + { + add => Manager.OnBeforeRenameFileAsync += value; + remove => Manager.OnBeforeRenameFileAsync -= value; + } + public event EventHandler OnBeforeDownloadFile; - + internal string ParentName { get; set; } + internal string DeletedFilesInputName { get; set; } + public bool ShowAddFiles { get; set; } - + public bool IsCollapseExpandedByDefault { get; set; } - + public string Title { get; set; } + public string SubTitle { get; set; } + public HeadingSize TitleSize { get; set; } = HeadingSize.H3; + public FontAwesomeIcon? Icon { get; set; } - + public bool ViewGallery { get; set; } - public Dictionary UserValues { get; set; } = new(); - + public string EmptyDataText { get; set; } = "There is no files to display."; + /// /// Always apply changes to the file system. - /// If false, keep it in the memory. + /// If false, keep it in the temp folder. /// (The default value is true.) /// public bool AutoSave { get; set; } = true; /// /// Full Directory Path. - /// (Optional) If the path is not given, all files will be stored in the session. + /// (Optional) If the path is not given, all files will be stored in the temp folder. /// /// /// Example: C:\temp\files\ (Windows) or /tmp/Files (Linux) /// public string FolderPath { get; set; } - public JJUploadArea UploadArea + + public string TempPath => TempPathFolder + DraftId.ToString("N") + "/"; + + + internal Guid DraftId { get { - if (_uploadArea != null) - return _uploadArea; - - _uploadArea = ComponentFactory.UploadArea.Create(); - _uploadArea.OnFileUploaded += OnFileUploaded; - _uploadArea.JsCallback = JsCallback; - _uploadArea.Name = $"{Name}-files"; + var draftIdStr = CurrentContext.HttpContext!.Request.GetValue($"{Name}-draft-id"); + if (!string.IsNullOrWhiteSpace(draftIdStr)) + return Guid.Parse(draftIdStr); - return _uploadArea; + return Guid.NewGuid(); } } - public string JsCallback { get; set; } = "getMasterDataForm().submit()"; - - public JJGridView GridView + public JJUploadArea UploadArea { get { - var files = GetFilesDataTable(); - - if (_gridView != null) - { - _gridView.DataSource = EnumerableHelper.ConvertToDictionaryList(files); - return _gridView; - } - - _gridView = ComponentFactory.GridView.Create(new FormElement(files)); - _gridView.FormElement.Name = Name; - _gridView.FormElement.ParentName = ParentName; - _gridView.FormElement.Title = Title; - _gridView.FormElement.SubTitle = SubTitle; - _gridView.FormElement.TitleSize = TitleSize; - _gridView.FormElement.Icon = Icon; - - _gridView.DataSource = EnumerableHelper.ConvertToDictionaryList(files); - _gridView.TotalOfRecords = files.Rows.Count; - - if(_gridView.FormElement.Fields.Contains("NameJS")) - _gridView.FormElement.Fields["NameJS"].VisibleExpression = "val:0"; - - if (_gridView.FormElement.Fields.Contains("LastWriteTime")) - _gridView.FormElement.Fields["LastWriteTime"].Label = "Last Modified"; - - _gridView.FormElement.Options.GridToolbarActions.InsertAction.SetVisible(false); - - _gridView.Name = $"{Name}-grid-view"; - _gridView.UserValues = UserValues; - _gridView.ShowPaging = false; - _gridView.ShowTitle = false; + if (field != null) + return field; + field = ComponentFactory.UploadArea.Create(); + field.OnFileUploadedAsync += OnFileUploadedAsync; + field.JsCallback = JsCallback; + field.Name = $"{Name}-files"; + field.QueryStringParams[$"{Name}-draft-id"] = DraftId.ToString("N"); - _gridView.FilterAction.SetVisible(false); - _gridView.EmptyDataText = StringLocalizer["There is no files to display."]; - _gridView.ShowHeaderWhenEmpty = false; - - _gridView.ViewAction.SetVisible(false); - _gridView.EditAction.SetVisible(false); - _gridView.DeleteAction.SetVisible(false); - _gridView.ExportAction.SetVisible(false); - _gridView.RefreshAction.SetVisible(false); - _gridView.ConfigAction.SetVisible(false); - - _gridView.TableActions.Add(DownloadAction); - - _gridView.OnRenderActionAsync += (_, args) => - { - if(args.ActionName.Equals(_downloadAction.Name)) - { - var fileName = args.FieldValues["Name"].ToString(); - var file = FormFileManager.GetFile(fileName); - var isInMemory = file?.IsInMemory ?? false; - var isRenamed = file?.IsRenamed ?? false; - if (isInMemory || isRenamed) - { - args.LinkButton.Enabled = false; - args.LinkButton.Tooltip = StringLocalizer["Save your form to download this file."]; - } - else - { - var downloader = ComponentFactory.Downloader.Create(); - downloader.FilePath = FormFileManager.GetFilePath(fileName); - args.LinkButton.UrlAction = downloader.GetDownloadUrl(); - } - } - - return ValueTaskHelper.CompletedTask; - }; - - _gridView.TableActions.Add(RenameAction); - _gridView.TableActions.Add(DeleteAction); - - - _gridView.FormElement.Options.Grid.RecordsPerPage = int.MaxValue; - _gridView.FormElement.Options.Grid.ShowPagging = false; - _gridView.FormElement.Options.Grid.ShowToolBar = false; - - return _gridView; + return field; } } - public UrlRedirectAction DownloadAction => - _downloadAction ??= new UrlRedirectAction - { - Icon = FontAwesomeIcon.CloudDownload, - Tooltip = "Download File", - Name = "download-file" - }; + public JJGridView GridView => field ??= CreateGridView(); - public ScriptAction DeleteAction + public string JsCallback { - get + get; + set { - if (_deleteAction != null) - return _deleteAction; - - _deleteAction = new ScriptAction - { - Icon = FontAwesomeIcon.Trash, - Tooltip = "Delete File", - OnClientClick = Scripts.GetDeleteFileScript(), - Name = "delete-file" - }; - - return _deleteAction; + field = value; + UploadArea?.JsCallback = value; } - } + } = "getMasterDataForm().submit()"; + + public UrlRedirectAction DownloadAction { get; } = new() + { + Icon = FontAwesomeIcon.CloudDownload, + Tooltip = "Download File", + Name = DownloadFileActionName + }; - public ScriptAction RenameAction + + public ScriptAction DeleteAction { get; } = new() { - get - { - if (_renameAction != null) - return _renameAction; - - _renameAction = new ScriptAction - { - Icon = FontAwesomeIcon.PencilSquareO, - Tooltip = "Rename File", - OnClientClick = Scripts.GetRenameFileScript(), - Name = "rename-file" - }; - _renameAction.SetVisible(false); - return _renameAction; - } - set => _renameAction = value; - } + Icon = FontAwesomeIcon.Trash, + Tooltip = "Delete File", + Name = DeleteFileActionName + }; - private FormFileManager FormFileManager + public ScriptAction RenameAction { get; } = new() { - get - { - if (_formFileManager == null) - { - _formFileManager = new FormFileManager($"{Name}-files", CurrentContext,StringLocalizer, LoggerFactory.CreateLogger()); - _formFileManager.OnBeforeCreateFile += OnBeforeCreateFile; - _formFileManager.OnBeforeDeleteFile += OnBeforeDeleteFile; - _formFileManager.OnBeforeRenameFile += OnBeforeRenameFile; - } - _formFileManager.AutoSave = AutoSave; - _formFileManager.FolderPath = FolderPath; - return _formFileManager; - } - } + Icon = FontAwesomeIcon.PencilSquareO, + Tooltip = "Rename File", + Name = RenameFileActionName + }; - private UploadViewScripts Scripts => _scripts ??= new UploadViewScripts(this); + private UploadViewScripts Scripts => field ??= new UploadViewScripts(this); - private IHttpContext CurrentContext { get; } + private IHttpContextAccessor CurrentContext { get; } private IComponentFactory ComponentFactory { get; } + private UploadViewManager Manager { get; } private IEncryptionService EncryptionService { get; } protected RouteContext RouteContext { get { - if (_routeContext != null) - return _routeContext; + if (field != null) + return field; - var factory = new RouteContextFactory(CurrentContext.Request.QueryString, EncryptionService); - _routeContext = factory.Create(); - - return _routeContext; + var factory = new RouteContextFactory(CurrentContext, EncryptionService); + field = factory.Create(); + + return field; } } internal IStringLocalizer StringLocalizer { get; } - private ILoggerFactory LoggerFactory { get; } + private ILogger Logger { get; } + public JJUploadView( - IHttpContext currentContext, + IHttpContextAccessor currentContext, IComponentFactory componentFactory, + UploadViewManager manager, IEncryptionService encryptionService, IStringLocalizer stringLocalizer, ILoggerFactory loggerFactory) { CurrentContext = currentContext; ComponentFactory = componentFactory; + Manager = manager; EncryptionService = encryptionService; StringLocalizer = stringLocalizer; - LoggerFactory = loggerFactory; Logger = loggerFactory.CreateLogger(); Name = "upload-view"; ShowAddFiles = true; IsCollapseExpandedByDefault = true; + + RenameAction.SetVisible(false); } - + protected override async Task BuildResultAsync() { if (RouteContext.ComponentContext is ComponentContext.DownloadFile) { var downloader = ComponentFactory.Downloader.Create(); - return downloader.GetDownloadResult(); + return await downloader.GetDownloadResultAsync(); } - + var uploadAreaResult = await UploadArea.GetResultAsync(); if (uploadAreaResult is JsonComponentResult) { return uploadAreaResult; } - - return await GetUploadViewResult(); + + return await GetUploadViewResult(appendHiddenInputs: true); } - public async Task GetUploadViewResult() + public async Task GetUploadViewResult(bool appendHiddenInputs) { var html = HtmlBuilder.Div(); - var uploadAction = CurrentContext.Request.Form[$"upload-view-action-{Name}"]; + var uploadAction = CurrentContext.HttpContext!.Request.GetFormValue($"upload-view-action-{Name}"); if (!string.IsNullOrEmpty(uploadAction)) { - var result = GetUploadActionResult(uploadAction); + var result = await GetUploadActionResultAsync(uploadAction); if (result is RenderedComponentResult renderedComponent) { @@ -350,44 +271,38 @@ public async Task GetUploadViewResult() html.Append(GetUploadAreaHtml()); + if (appendHiddenInputs) + html.Append(GetHiddenInputsHtmlAsync()); + if (ViewGallery) { html.Append(await GetGalleryHtml()); } else { - var result = await GetGridViewResult(); - - if (result is RenderedComponentResult renderedComponent) - { - html.Append(renderedComponent.HtmlBuilder); - } - else - { - return result; - } + html.Append(await GetFilesGridHtmlAsync()); } html.AppendComponent(await GetPreviewModalHtml()); html.WithId(Name); - + return new RenderedComponentResult(html); } - private ComponentResult GetUploadActionResult(string uploadViewAction) + private async Task GetUploadActionResultAsync(string uploadViewAction) { - var fileName = CurrentContext.Request.Form[$"upload-view-file-name-{Name}"]; + var fileName = CurrentContext.HttpContext!.Request.GetFormValue($"upload-view-file-name-{Name}"); try { switch (uploadViewAction) { case "deleteFile": - return GetDeleteFileResult(fileName); + return await GetDeleteFileResultAsync(fileName); case "downloadFile": - return GetDownloadFileResult(Path.Combine(FormFileManager.FolderPath, fileName)); + return await GetDownloadFileResultAsync(fileName); case "renameFile": - return GetRenameFileResult(fileName); + return await GetRenameFileResultAsync(fileName); } } catch (Exception ex) @@ -408,14 +323,12 @@ private ComponentResult GetUploadActionResult(string uploadViewAction) private HtmlBuilder GetUploadAreaHtml() { - var html = new HtmlBuilder() - .AppendHiddenInput($"upload-view-action-{Name}") - .AppendHiddenInput($"upload-view-file-name-{Name}"); + var html = new HtmlBuilder(); if (!ShowAddFiles) return html; - html.AppendComponent(new JJMasterDataCollapsePanel(CurrentContext.Request.Form) + html.AppendComponent(new JJMasterDataCollapsePanel(CurrentContext) { Title = StringLocalizer["New File"], ExpandedByDefault = IsCollapseExpandedByDefault, @@ -425,6 +338,19 @@ private HtmlBuilder GetUploadAreaHtml() return html; } + internal HtmlBuilder GetHiddenInputsHtmlAsync() + { + var html = new HtmlBuilder() + .AppendHiddenInput($"upload-view-action-{Name}") + .AppendHiddenInput($"upload-view-file-name-{Name}") + .AppendHiddenInput($"{Name}-draft-id", DraftId.ToString("N")); + + if (!AutoSave && !string.IsNullOrWhiteSpace(DeletedFilesInputName)) + html.AppendHiddenInput(DeletedFilesInputName, GetDeletedFilesByComma()); + + return html; + } + private HtmlBuilder GetHtmlFormPanel() { var panelContent = new HtmlBuilder(); @@ -436,55 +362,44 @@ private HtmlBuilder GetHtmlFormPanel() }; panelContent.AppendComponent(label); } - + panelContent.Append(UploadArea.GetUploadAreaHtmlBuilder()); return panelContent; } - private Task GetGridViewResult() - { - return GridView.GetResultAsync(); - - } - private async Task GetGalleryHtml() { - var files = GetFiles().FindAll(x => !x.Deleted); - if (files.Count == 0) - return new JJAlert{Title = StringLocalizer["There is no files to display."]}.GetHtmlBuilder(); + var files = await GetFilesAsync(); + if (files.Count == 0) + return new JJAlert { Title = StringLocalizer[EmptyDataText] }.GetHtmlBuilder(); - foreach (var ac in GridView.TableActions) - { - ac.IsGroup = false; - } + var row = HtmlBuilder.Div().WithCssClass("row"); - var row = new HtmlBuilder(HtmlTag.Div) - .WithCssClass("row"); - - foreach (var fileInfo in files) + foreach (var file in files) { - var file = fileInfo.Content; - var col = new HtmlBuilder(HtmlTag.Div); + var col = HtmlBuilder.Div(); col.WithCssClass("col-sm-3"); - - var fileValues = ConvertFormFileToDictionary(file); - var formStateData = new FormStateData(fileValues, UserValues, PageState.List); - var actionsHtml = await GridView.Table.Body.GetActionsHtmlListAsync(formStateData); - + + var previewHtml = GetHtmlGalleryPreview(file); + var actionsHtml = GetFileActions(file); + col.Append(HtmlTag.Ul, ul => { ul.WithCssClass("list-group list-group-flush"); - ul.Append(GetHtmlGalleryPreview(file.FileName)); - + ul.Append(previewHtml); + ul.AppendRange(GetGalleryListItems(file)); - + ul.Append(HtmlTag.Li, li => { li.WithCssClass("list-group-item"); li.Append(HtmlTag.Table, table => { table.WithCssClass("table-gallery"); - table.AppendRange(actionsHtml); + table.Append(HtmlTag.Tr, tr => + { + tr.AppendRange(actionsHtml); + }); }); }); }); @@ -494,8 +409,8 @@ private async Task GetGalleryHtml() return row; } - - private IEnumerable GetGalleryListItems(FormFileContent file) + + private IEnumerable GetGalleryListItems(FileStorageItem file) { yield return GetHtmlGalleryListItem("Name", file.FileName); yield return GetHtmlGalleryListItem("Size", $"{file.Length} Bytes"); @@ -506,24 +421,22 @@ private HtmlBuilder GetHtmlGalleryListItem(string label, string value) { return new HtmlBuilder(HtmlTag.Li) .WithCssClass("list-group-item") - .Append(HtmlTag.B, b => - { - b.AppendText(StringLocalizer[label]); - }) + .Append(HtmlTag.B, b => { b.AppendText(StringLocalizer[label]); }) .AppendText(value); } - private HtmlBuilder GetHtmlGalleryPreview(string fileName) + private HtmlBuilder GetHtmlGalleryPreview(FileStorageItem file) { var html = new HtmlBuilder(HtmlTag.Li) .WithCssClass("list-group-item"); + var fileName = file.FileName; switch (Path.GetExtension(fileName)) { case ".png": case ".jpg": case ".jpeg": - html.Append(GetHtmlImageBox(fileName)); + html.Append(GetHtmlImageBox(file)); break; case ".mp4": html.WithCssClass("text-center"); @@ -531,39 +444,39 @@ private HtmlBuilder GetHtmlGalleryPreview(string fileName) break; case ".pdf": html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-pdf-o", "red")); break; case ".pptx": html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-powerpoint-o", "red")); break; case ".docx": html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-word-o", "blue")); break; case ".csv": case ".txt": html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-text-o", "black")); break; case ".xls": html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-excel-o", "green")); break; case ".rar": case ".zip": html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-zip-o", "#d2bb1c")); break; default: html.WithCssClass("text-center"); - html.WithStyle( "background-color:#f5f5f5"); + html.WithStyle("background-color:#f5f5f5"); html.Append(GetHtmlItemBox(fileName, "fa fa-file-o", "gray")); break; } @@ -574,43 +487,31 @@ private HtmlBuilder GetHtmlGalleryPreview(string fileName) private static HtmlBuilder GetHtmlItemBox(string fileName, string cssIcon, string colorIcon) { var div = new HtmlBuilder(HtmlTag.Div) - .WithStyle( "height:180px;") + .WithStyle("height:180px;") .Append(HtmlTag.Span, span => { span.WithCssClass(cssIcon) .WithToolTip(fileName) - .WithStyle( $"color:{colorIcon};padding-top:45px;font-size:100px;"); + .WithStyle($"color:{colorIcon};padding-top:45px;font-size:100px;"); }); return div; } - private HtmlBuilder GetHtmlImageBox(string fileName) + private HtmlBuilder GetHtmlImageBox(FileStorageItem file) { - var file = FormFileManager.GetFile(fileName); + var downloader = ComponentFactory.Downloader.Create(); + + downloader.FullPath = file.FullPath; + var src = downloader.GetDownloadUrl(); - string src; - - if (file.IsInMemory) - { - var base64 = Convert.ToBase64String(file.Content.Bytes.ToArray()); - src = $"data:image/{Path.GetExtension(fileName).Replace(".", "")};base64,{base64}"; - } - else - { - var filePath = Path.Combine(FormFileManager.FolderPath, fileName); - var downloader = ComponentFactory.Downloader.Create(); - downloader.FilePath = filePath; - src = downloader.GetDownloadUrl(); - } - var html = new HtmlBuilder(HtmlTag.Img); html.WithAttribute("loading", "lazy") .WithAttribute("src", src) - .WithStyle( "height:180px;") + .WithStyle("height:180px;") .WithCssClass("img-responsive") - .WithToolTip(fileName); - + .WithToolTip(file.FileName); + return html; } @@ -621,19 +522,6 @@ private static HtmlBuilder GetHtmlVideoBox(string fileName) return html; } - private static Dictionary ConvertFormFileToDictionary(FormFileContent file) - { - var dictionary = new Dictionary - { - { FileName, file.FileName }, - { LastWriteTime, file.LastWriteTime }, - { Size, file.Length }, - { FileNameJs, file.FileName.Replace("'", "\\'") } - }; - - return dictionary; - } - private async Task GetPreviewModalHtml() { var html = new HtmlBuilder(HtmlTag.Div); @@ -650,7 +538,7 @@ private async Task GetPreviewModalHtml() group.Text = "image"; var groupHtml = await group.GetHtmlBuilderAsync(); - + html.Append(HtmlTag.Div, row => { row.WithCssClass("row"); @@ -676,9 +564,9 @@ private async Task GetPreviewModalHtml() col.Append(HtmlTag.Img, img => { img.WithAttribute("id", "pastedimage_0") - .WithStyle( "max-height:350px;") - .WithAttribute("alt", StringLocalizer["Preview Image"]) - .WithCssClass("img-responsive"); + .WithStyle("max-height:350px;") + .WithAttribute("alt", StringLocalizer["Preview Image"]) + .WithCssClass("img-responsive"); }); }); }); @@ -710,34 +598,161 @@ private async Task GetPreviewModalHtml() return modal; } - private DataTable GetFilesDataTable() + private async Task GetFilesGridHtmlAsync() + { + var files = await GetFilesAsync(); + + GridView.EmptyDataText = EmptyDataText; + GridView.TotalOfRecords = files.Count; + GridView.DataSource = files.Select(file => new Dictionary + { + [FileNameField] = file.FileName, + [FileSizeField] = Format.FormatFileSize(file.Length), + [LastModifiedField] = file.LastWriteTime.ToString(CultureInfo.CurrentCulture), + [FullPathField] = file.FullPath, + [FolderPathField] = file.FolderPath + }).ToList(); + + return await GridView.GetHtmlBuilderAsync(); + } + + private JJGridView CreateGridView() + { + var gridName = $"{Name}-files-grid"; + var formElement = new FormElement + { + Name = gridName, + TableName = gridName + }; + + formElement.Fields.AddRange([ + new FormElementField { Name = FileNameField, Label = "Name" }, + new FormElementField { Name = FileSizeField, Label = "Size" }, + new FormElementField { Name = LastModifiedField, Label = "Last Modified" } + ]); + formElement.Options.Grid.IsCompact = true; + + formElement.Options.GridTableActions.Clear(); + formElement.Options.GridTableActions.AddRange([DownloadAction, RenameAction, DeleteAction]); + + var gridView = ComponentFactory.GridView.Create(formElement); + gridView.ShowTitle = false; + gridView.ShowToolbar = false; + gridView.EnableFilter = false; + gridView.EnableSorting = false; + gridView.ShowPaging = false; + gridView.ShowHeaderWhenEmpty = false; + gridView.FilterAction.SetVisible(false); + gridView.SortAction.SetVisible(false); + gridView.OnRenderAction += OnRenderGridAction; + + return gridView; + } + + private void OnRenderGridAction(object sender, ActionEventArgs args) { - var files = FormFileManager.GetFiles(); - var dt = new DataTable(); - dt.Columns.Add(FileName, typeof(string)); - dt.Columns.Add(Size, typeof(string)); - dt.Columns.Add(LastWriteTime, typeof(string)); - dt.Columns.Add(FileNameJs, typeof(string)); + var fileName = args.FieldValues[FileNameField]?.ToString() ?? string.Empty; - foreach (var fileInfo in files.Where(f => !f.Deleted)) + switch (args.ActionName) { - var content = fileInfo.Content; - var dataRow = dt.NewRow(); - dataRow["Name"] = content.FileName; - dataRow["Size"] = Format.FormatFileSize(content.Length); - dataRow["LastWriteTime"] = content.LastWriteTime.ToDateTimeString(); - dataRow["NameJS"] = HttpUtility.JavaScriptStringEncode(content.FileName); - dt.Rows.Add(dataRow); + case DownloadFileActionName: + var fullPath = args.FieldValues[FullPathField]?.ToString(); + args.LinkButton.UrlAction = ComponentFactory.Downloader.Create(fullPath).GetDownloadUrl(); + args.LinkButton.OnClientClick = null; + break; + case RenameFileActionName: + var folderPath = args.FieldValues[FolderPathField]?.ToString(); + args.LinkButton.OnClientClick = GetActionScript(Scripts.GetRenameFileScript(), fileName); + if (!AutoSave && !string.Equals(folderPath, TempPath, StringComparison.Ordinal)) + args.LinkButton.Enabled = false; + break; + case DeleteFileActionName: + var isDraft = string.Equals( + args.FieldValues[FolderPathField]?.ToString(), + TempPath, + StringComparison.Ordinal); + var deleteScript = !AutoSave && !isDraft + ? Scripts.GetMarkDeletedScript() + : Scripts.GetDeleteFileScript(); + args.LinkButton.OnClientClick = GetActionScript(deleteScript, fileName); + break; + } + } + + private IEnumerable GetFileActions(FileStorageItem file) + { + var isDraft = file.FolderPath.Equals(TempPath); + + if (DownloadAction.IsVisible) + { + var downloader = ComponentFactory.Downloader.Create(file.FullPath); + var actionButton = CreateActionButton(DownloadAction, urlAction: downloader.GetDownloadUrl()); + + yield return CreateActionCell(actionButton); + } + + if (RenameAction.IsVisible) + { + var actionButton = CreateActionButton( + RenameAction, + onClientClick: GetActionScript(Scripts.GetRenameFileScript(), file.FileName)); + + if (!AutoSave && !isDraft) + actionButton.Enabled = false; + + yield return CreateActionCell(actionButton); + } + + if (DeleteAction.IsVisible) + { + var deleteScript = !AutoSave && !isDraft + ? Scripts.GetMarkDeletedScript() + : Scripts.GetDeleteFileScript(); + + var actionButton = CreateActionButton( + DeleteAction, + onClientClick: GetActionScript(deleteScript, file.FileName)); + + yield return CreateActionCell(actionButton); } + } + + private static HtmlBuilder CreateActionCell(JJLinkButton actionButton) + { + var td = new HtmlBuilder(HtmlTag.Td); + td.WithCssClass("table-action"); + td.AppendComponent(actionButton); + + return td; + } + + private static JJLinkButton CreateActionButton(BasicAction action, string urlAction = null, + string onClientClick = null) + { + return new JJLinkButton + { + Text = action.ShowTitle ? action.Text : null, + Tooltip = action.Tooltip, + UrlAction = urlAction, + OnClientClick = onClientClick, + IconClass = $"{action.Icon.CssClass} fa-fw", + ShowAsButton = action.ShowAsButton, + CssClass = action.CssClass, + Visible = action.IsVisible + }; + } - return dt; + private static string GetActionScript(string script, string fileName) + { + var fileNameJs = HttpUtility.JavaScriptStringEncode(fileName); + return script.Replace($"{{{FileNameJs}}}", fileNameJs); } - private void OnFileUploaded(object sender, FormUploadFileEventArgs args) + private async ValueTask OnFileUploadedAsync(object sender, FormUploadFileEventArgs args) { try { - CreateFile(args.File); + await CreateFileAsync(args.File); args.SuccessMessage = "File successfully created."; } catch (Exception ex) @@ -746,12 +761,12 @@ private void OnFileUploaded(object sender, FormUploadFileEventArgs args) } } - private RenderedComponentResult GetRenameFileResult(string fileName) + private async Task GetRenameFileResultAsync(string fileName) { var names = fileName.Split(';'); var currentName = names[0]; var newName = names[1]; - RenameFile(currentName, newName); + await RenameFileAsync(currentName, newName); var text = StringLocalizer["File successfully renamed."]; var alert = new JJAlert @@ -765,15 +780,18 @@ private RenderedComponentResult GetRenameFileResult(string fileName) return new RenderedComponentResult(alert.GetHtmlBuilder()); } - public void RenameFile(string currentName, string newName) => - FormFileManager.RenameFile(currentName, newName); + public Task RenameFileAsync(string currentName, string newName) => + Manager.RenameFileAsync(TempPath, FolderPath, currentName, newName); - public void CreateFile(FormFileContent file) => - FormFileManager.CreateFile(file, !UploadArea.Multiple); + public Task CreateFileAsync(IFormFile file) => + Manager.CreateFileAsync(TempPath, FolderPath, AutoSave, file, UploadArea.Multiple); - public ComponentResult GetDeleteFileResult(string fileName) + public Task DeleteFileAsync(string fileName) => + Manager.DeleteFileAsync(TempPath, FolderPath, fileName); + + private async Task GetDeleteFileResultAsync(string fileName) { - FormFileManager.DeleteFile(fileName); + await DeleteFileAsync(fileName); var text = StringLocalizer["File successfully deleted."]; var alert = new JJAlert { @@ -785,27 +803,36 @@ public ComponentResult GetDeleteFileResult(string fileName) return new RenderedComponentResult(alert.GetHtmlBuilder()); } - - internal void DeleteAll() => - FormFileManager.DeleteAll(); - public List GetFiles() => - FormFileManager.GetFiles(); + public Task DeleteAllAsync() => + Manager.DeleteAllAsync(TempPath, FolderPath, AutoSave); - public void ClearMemoryFiles() => - FormFileManager.MemoryFiles = null; + public async Task> GetFilesAsync() + { + var files = await Manager.GetFilesAsync(TempPath, FolderPath); + + var deletedFiles = GetDeletedFiles(); + + if (!AutoSave && deletedFiles.Count > 0) + files.RemoveAll(file => !file.FolderPath.Equals(TempPath) && deletedFiles.Contains(file.FileName)); + + return files; + } - public void SaveMemoryFiles(string folderPath) => - FormFileManager.SaveMemoryFiles(folderPath); + public Task ClearTemporaryFilesAsync() => + Manager.DeleteAllAsync(TempPath, null, false); - public FileComponentResult GetDownloadFileResult(string fileName) + public Task PromoteDraftFilesAsync() => + Manager.PromoteDraftFilesAsync(TempPath, FolderPath, GetDeletedFiles()); + + public async Task GetDownloadFileResultAsync(string fileName) { if (OnBeforeDownloadFile != null) { var args = new FormDownloadFileEventArgs(fileName, null); - OnBeforeDownloadFile.Invoke(this, args); + OnBeforeDownloadFile(this, args); + - if (!string.IsNullOrEmpty(args.ErrorMessage)) { var exception = new JJMasterDataException(args.ErrorMessage); @@ -813,9 +840,13 @@ public FileComponentResult GetDownloadFileResult(string fileName) throw exception; } } - var downloader = ComponentFactory.Downloader.Create(); - downloader.FilePath = fileName; - return downloader.GetDownloadResult(); + + var file = await Manager.GetFileAsync(TempPath, FolderPath, fileName); + if (file == null) + throw new JJMasterDataException(StringLocalizer["File not found."]); + + var downloader = ComponentFactory.Downloader.Create(file.FullPath); + return await downloader.GetDirectDownloadResultAsync(); } /// @@ -824,11 +855,30 @@ public FileComponentResult GetDownloadFileResult(string fileName) public void Disable() { ShowAddFiles = false; - foreach (var action in GridView.TableActions) - { - action.SetVisible(false); - } + RenameAction.SetVisible(false); + DeleteAction.SetVisible(false); DownloadAction.SetVisible(true); } + private string GetDeletedFilesByComma() + { + if (string.IsNullOrWhiteSpace(DeletedFilesInputName)) + return string.Empty; + + return CurrentContext.HttpContext!.Request.GetValue(DeletedFilesInputName) ?? string.Empty; + } + + private HashSet GetDeletedFiles() + { + var values = GetDeletedFilesByComma(); + if (string.IsNullOrWhiteSpace(values)) + return []; + + return values + .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(Path.GetFileName) + .Where(name => !string.IsNullOrWhiteSpace(name)) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + } + } diff --git a/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewFactory.cs b/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewFactory.cs index 751f9c523..ab3c0817b 100644 --- a/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewFactory.cs +++ b/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewFactory.cs @@ -1,12 +1,17 @@ +#nullable disable warnings +using System.Collections.Generic; using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Core.Http.Abstractions; +using JJMasterData.Commons.Storage; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataManager; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; namespace JJMasterData.Core.UI.Components; -public sealed class UploadViewFactory(IHttpContext currentContext, +public sealed class UploadViewFactory(IHttpContextAccessor currentContext, IComponentFactory componentFactory, + UploadViewManager manager, IEncryptionService encryptionService, IStringLocalizer stringLocalizer, ILoggerFactory loggerFactory) @@ -16,8 +21,43 @@ public JJUploadView Create() return new JJUploadView( currentContext, componentFactory, + manager, encryptionService, stringLocalizer, loggerFactory); } -} \ No newline at end of file + + + public JJUploadView Create( + FormElement formElement, + FormElementField field, + Dictionary values) + { + var uploadView = Create(); + + uploadView.Name = $"{field.Name}-upload-view"; + uploadView.ParentName = formElement.ParentName; //Atençao verificar se he nulo no JJTextFile + uploadView.Title = string.Empty; + uploadView.AutoSave = false; + uploadView.DeletedFilesInputName = UploadViewManager.GetDeletedFilesInputName(field); + + uploadView.RenameAction.SetVisible(true); + + if (DataHelper.ContainsPkValues(formElement, values)) + uploadView.FolderPath = FileStoragePath.GetFolderPath(formElement, field, values); + + var dataFile = field.DataFile!; + uploadView.UploadArea.Multiple = dataFile.MultipleFile; + uploadView.UploadArea.MaxFileSize = dataFile.MaxFileSize; + uploadView.UploadArea.ShowFileSize = dataFile.ExportAsLink; + uploadView.UploadArea.AllowedTypes = dataFile.AllowedTypes; + uploadView.UploadArea.EnableCopyPaste = dataFile.AllowPasting; + uploadView.UploadArea.RouteContext.ElementName = formElement.Name; + uploadView.UploadArea.RouteContext.ParentElementName = formElement.ParentName; + uploadView.UploadArea.RouteContext.ComponentContext = ComponentContext.TextFileFileUpload; + uploadView.UploadArea.QueryStringParams["fieldName"] = field.Name; + uploadView.ViewGallery = dataFile.ViewGallery; + + return uploadView; + } +} diff --git a/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewManager.cs b/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewManager.cs new file mode 100644 index 000000000..80954f42a --- /dev/null +++ b/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewManager.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using JJConsulting.MasterData.Storage.Abstractions; +using JJMasterData.Commons.Exceptions; +using JJMasterData.Commons.Storage; +using JJMasterData.Commons.Tasks; +using JJMasterData.Commons.Util; +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataManager; +using JJMasterData.Core.DataManager.Services; +using JJMasterData.Core.UI.Events.Args; +using Microsoft.Extensions.Localization; + +namespace JJMasterData.Core.UI.Components; + +public class UploadViewManager( + IHttpContextAccessor currentContext, + ElementFileService elementFileService, + IFileStorage fileStorage, + IStringLocalizer stringLocalizer) +{ + public event AsyncEventHandler? OnBeforeCreateFileAsync; + public event AsyncEventHandler? OnBeforeDeleteFileAsync; + public event AsyncEventHandler? OnBeforeRenameFileAsync; + + + public async Task> GetFilesAsync(string tempPath, string? folderPath) + { + var files = new List(); + files.AddRange(await fileStorage.ListAsync(tempPath)); + + if (string.IsNullOrEmpty(folderPath)) + return files; + + var savedFiles = await fileStorage.ListAsync(folderPath); + foreach (var file in savedFiles) + { + if (files.Any(x => x.FileName.Equals(file.FileName))) + continue; + + files.Add(file); + } + + return files; + } + + public async Task RenameFileAsync( + string tempPath, + string folderPath, + string currentName, + string newName) + { + if (string.IsNullOrEmpty(currentName)) + throw new ArgumentNullException(nameof(currentName)); + + if (string.IsNullOrWhiteSpace(newName)) + throw new ArgumentNullException(stringLocalizer["Required file name"]); + + currentName = Path.GetFileName(currentName); + newName = Path.GetFileName(newName); + + if (!FileIO.GetFileNameExtension(currentName).Equals(FileIO.GetFileNameExtension(newName))) + throw new JJMasterDataException(stringLocalizer["The file extension must remain the same"]); + + if ((await GetFilesAsync(tempPath, folderPath)).Exists(x => x.FileName.Equals(newName))) + throw new JJMasterDataException(stringLocalizer["A file with the name {0} already exists", newName]); + + if (OnBeforeRenameFileAsync != null) + { + var args = new FormRenameFileEventArgs(currentName, newName); + await OnBeforeRenameFileAsync(this, args); + + if (!string.IsNullOrEmpty(args.ErrorMessage)) + throw new JJMasterDataException(args.ErrorMessage); + } + + var file = await GetFileAsync(tempPath, folderPath, currentName); + if (file == null) + throw new JJMasterDataException(stringLocalizer["file {0} not found!", currentName]); + + await elementFileService.RenameFileAsync(file.FolderPath, currentName, newName); + } + + public async Task GetFileAsync(string tempPath, string folderPath, string fileName) + { + fileName = Path.GetFileName(fileName); + var files = await GetFilesAsync(tempPath, folderPath); + return files.Find(x => fileName.Equals(x.FileName)); + } + + public async Task CreateFileAsync( + string tempPath, + string folderPath, + bool autoSave, + IFormFile file, + bool isMultipleFiles) + { + if (file == null) + throw new ArgumentNullException(nameof(file)); + + if (OnBeforeCreateFileAsync != null) + { + var args = new FormUploadFileEventArgs(file); + await OnBeforeCreateFileAsync(this, args); + string errorMessage = args.ErrorMessage; + + if (!string.IsNullOrEmpty(errorMessage)) + throw new JJMasterDataException(errorMessage); + + file = args.File; + } + + if (!isMultipleFiles) + await DeleteAllAsync(tempPath, folderPath, autoSave); + + var storageFolderPath = autoSave + ? folderPath + : tempPath; + + await elementFileService.SaveFileAsync(storageFolderPath, file); + } + + public async Task DeleteFileAsync( + string tempPath, + string folderPath, + string fileName) + { + fileName = Path.GetFileName(fileName); + + if (OnBeforeDeleteFileAsync != null) + { + var args = new FormDeleteFileEventArgs(fileName); + await OnBeforeDeleteFileAsync(this, args); + + if (!string.IsNullOrEmpty(args.ErrorMessage)) + throw new JJMasterDataException(args.ErrorMessage); + } + + var files = await GetFilesAsync(tempPath, folderPath); + foreach (var file in files) + { + if (file.FileName.Equals(fileName)) + await elementFileService.DeleteFileAsync(file.FolderPath, file.FileName); + } + } + + public async Task DeleteAllAsync(string tempPath, string? folderPath, bool autoSave) + { + await fileStorage.DeleteFolderAsync(tempPath); + + if (autoSave && !string.IsNullOrEmpty(folderPath)) + await fileStorage.DeleteFolderAsync(folderPath); + } + + public async Task ClearTemporaryFilesAsync(FormElement formElement) + { + foreach (var field in GetFileFields(formElement)) + { + var tempPath = GetTempPath(field); + if (string.IsNullOrEmpty(tempPath)) + continue; + + await DeleteAllAsync(tempPath, null, false); + } + } + + public async Task PromoteDraftFilesAsync(string tempPath, string folderPath, HashSet deletedFiles) + { + foreach (var fileName in deletedFiles) + { + if (string.IsNullOrWhiteSpace(fileName)) + continue; + + await elementFileService.DeleteFileAsync(folderPath, Path.GetFileName(fileName)); + } + + var files = await fileStorage.ListAsync(tempPath); + foreach (var file in files) + { + var destination = FileStoragePath.Combine(folderPath, file.FileName); + await fileStorage.MoveAsync(file.FullPath, destination); + } + + await fileStorage.DeleteFolderAsync(tempPath); + } + + public async Task PromoteDraftFilesAsync(FormElement formElement, Dictionary values) + { + if (!DataHelper.ContainsPkValues(formElement, values!)) + return; + + foreach (var field in GetFileFields(formElement)) + { + var tempPath = GetTempPath(field); + if (string.IsNullOrEmpty(tempPath)) + continue; + + var folderPath = FileStoragePath.GetFolderPath(formElement, field, values); + await PromoteDraftFilesAsync(tempPath, folderPath, GetDeletedFiles(field)); + } + } + + private string? GetTempPath(FormElementField field) + { + var draftIdStr = currentContext.HttpContext?.Request.GetValue($"{GetUploadViewName(field)}-draft-id"); + if (!Guid.TryParse(draftIdStr, out var draftId)) + return null; + + return JJUploadView.TempPathFolder + draftId.ToString("N") + "/"; + } + + private HashSet GetDeletedFiles(FormElementField field) + { + var values = currentContext.HttpContext?.Request.GetValue(GetDeletedFilesInputName(field)); + if (string.IsNullOrWhiteSpace(values)) + return []; + + return values + .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(Path.GetFileName) + .Where(name => !string.IsNullOrWhiteSpace(name)) + .Select(name => name!) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + } + + private static string GetUploadViewName(FormElementField field) => + $"{field.Name}-upload-view"; + + internal static string GetDeletedFilesInputName(FormElementField field) => + $"{GetUploadViewName(field)}-files-deleted"; + + private static IEnumerable GetFileFields(FormElement formElement) + { + foreach (var field in formElement.Fields) + { + if (field.Component is FormComponent.File && field.DataFile is not null) + yield return field; + } + } +} diff --git a/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewScripts.cs b/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewScripts.cs index 3abb3ff56..717328361 100644 --- a/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewScripts.cs +++ b/src/MasterData.Core/UI/Components/IO/UploadView/UploadViewScripts.cs @@ -12,6 +12,13 @@ public string GetDeleteFileScript() //language=Javascript return $"UploadViewHelper.deleteFile('{uploadView.Name}','{{NameJS}}','{message}','{JsCallBack}');"; } + + public string GetMarkDeletedScript() + { + string message = uploadView.StringLocalizer["Would you like to delete this record?"]; + //language=Javascript + return $"UploadViewHelper.markDeleted('{uploadView.Name}','{{NameJS}}','{message}','{JsCallBack}','{uploadView.DeletedFilesInputName}');"; + } public string GetDownloadFileScript() { @@ -25,4 +32,4 @@ public string GetRenameFileScript() //language=Javascript return $"UploadViewHelper.renameFile('{uploadView.Name}','{{NameJS}}','{message}','{JsCallBack}');"; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/Importation/DataImportationFactory.cs b/src/MasterData.Core/UI/Components/Importation/DataImportationFactory.cs index bcbb248d5..ad3b91293 100644 --- a/src/MasterData.Core/UI/Components/Importation/DataImportationFactory.cs +++ b/src/MasterData.Core/UI/Components/Importation/DataImportationFactory.cs @@ -11,7 +11,6 @@ using JJMasterData.Core.DataManager.Services; using JJMasterData.Core.Events.Abstractions; using JJMasterData.Core.Events.Args; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; @@ -24,7 +23,7 @@ internal sealed class DataImportationFactory( FieldValuesService fieldValuesService, FormService formService, IBackgroundTaskManager backgroundTaskManager, - IHttpContext httpContext, + IHttpContextAccessor httpContext, IMasterDataUser masterDataUser, IComponentFactory componentFactory, DataItemService dataItemService, @@ -59,7 +58,7 @@ public async ValueTask CreateAsync(string elementName) var formElement = await dataDictionaryRepository.GetFormElementAsync(elementName); - var dataContext = new DataContext(httpContext.Request, DataContextSource.Upload, masterDataUser.Id); + var dataContext = new DataContext(httpContext.HttpContext?.Request, DataContextSource.Upload, masterDataUser.Id); var formEvent = formEventHandlerResolver.GetFormEventHandler(elementName); diff --git a/src/MasterData.Core/UI/Components/Importation/DataImportationHelp.cs b/src/MasterData.Core/UI/Components/Importation/DataImportationHelp.cs index 81c5dd3da..70e029d18 100644 --- a/src/MasterData.Core/UI/Components/Importation/DataImportationHelp.cs +++ b/src/MasterData.Core/UI/Components/Importation/DataImportationHelp.cs @@ -1,7 +1,7 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.Globalization; -using System.Text; using System.Threading.Tasks; using JJConsulting.FontAwesome; using JJConsulting.Html; @@ -13,7 +13,6 @@ using JJMasterData.Commons.Util; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Models; -using JJMasterData.Core.Extensions; using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/Importation/DataImportationLog.cs b/src/MasterData.Core/UI/Components/Importation/DataImportationLog.cs index f9a193b5e..79b120e8c 100644 --- a/src/MasterData.Core/UI/Components/Importation/DataImportationLog.cs +++ b/src/MasterData.Core/UI/Components/Importation/DataImportationLog.cs @@ -7,12 +7,7 @@ using JJConsulting.Html.Bootstrap.Models; using JJConsulting.Html.Extensions; using JJMasterData.Commons.Util; -using JJMasterData.Core.DataDictionary; -using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager.Importation; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; - using Microsoft.Extensions.Localization; namespace JJMasterData.Core.UI.Components; @@ -21,11 +16,10 @@ internal sealed class DataImportationLog { private readonly DataImportationReporter _reporter; private readonly IStringLocalizer _stringLocalizer; - private readonly IHttpContext _currentContext; + internal DataImportationLog(JJDataImportation dataImportation) { _stringLocalizer = dataImportation.StringLocalizer; - _currentContext = dataImportation.CurrentContext; _reporter = dataImportation.GetCurrentReporter(); } diff --git a/src/MasterData.Core/UI/Components/Importation/DataImportationScripts.cs b/src/MasterData.Core/UI/Components/Importation/DataImportationScripts.cs index 9e0a242ec..241647a61 100644 --- a/src/MasterData.Core/UI/Components/Importation/DataImportationScripts.cs +++ b/src/MasterData.Core/UI/Components/Importation/DataImportationScripts.cs @@ -1,8 +1,5 @@ -#nullable enable - using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.Extensions; using JJMasterData.Core.UI.Routing; using Microsoft.Extensions.Localization; diff --git a/src/MasterData.Core/UI/Components/Importation/JJDataImportation.cs b/src/MasterData.Core/UI/Components/Importation/JJDataImportation.cs index 191040dcf..5e6d0d5db 100644 --- a/src/MasterData.Core/UI/Components/Importation/JJDataImportation.cs +++ b/src/MasterData.Core/UI/Components/Importation/JJDataImportation.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -13,7 +14,6 @@ using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Commons.Tasks; using JJMasterData.Commons.Tasks.Progress; -using JJMasterData.Core.DataDictionary; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataDictionary.Models.Actions; using JJMasterData.Core.DataManager; @@ -22,9 +22,6 @@ using JJMasterData.Core.DataManager.Models; using JJMasterData.Core.DataManager.Services; using JJMasterData.Core.Events.Args; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Html; -using JJMasterData.Core.Http.Abstractions; using JJMasterData.Core.UI.Events.Args; using JJMasterData.Core.UI.Routing; @@ -91,7 +88,7 @@ private RouteContext RouteContext if (_routeContext != null) return _routeContext; - var factory = new RouteContextFactory(CurrentContext.Request.QueryString, EncryptionService); + var factory = new RouteContextFactory(HttpContextAccessor, EncryptionService); _routeContext = factory.Create(); return _routeContext; @@ -116,17 +113,17 @@ public JJDataImportation( FormService formService, FieldValuesService fieldValuesService, IBackgroundTaskManager backgroundTaskManager, - IHttpContext currentContext, + IHttpContextAccessor httpContextAccessor, IComponentFactory componentFactory, DataItemService dataItemService, DataImportationWorkerFactory dataImportationWorkerFactory, IEncryptionService encryptionService, ILoggerFactory loggerFactory, IStringLocalizer stringLocalizer) - : base(currentContext,masterDataUser, expressionsService, backgroundTaskManager, + : base(httpContextAccessor,masterDataUser, expressionsService, backgroundTaskManager, loggerFactory.CreateLogger(), encryptionService, stringLocalizer) { - CurrentContext = currentContext; + HttpContextAccessor = httpContextAccessor; DataImportationWorkerFactory = dataImportationWorkerFactory; FormService = formService; FieldValuesService = fieldValuesService; @@ -152,7 +149,7 @@ protected override async Task BuildResultAsync() return await UploadArea.GetResultAsync(); } - string action = CurrentContext.Request.QueryString["dataImportationOperation"]; + string action = HttpContextAccessor.HttpContext!.Request.Query["dataImportationOperation"]; switch (action) { @@ -175,7 +172,7 @@ protected override async Task BuildResultAsync() { if (!IsRunning()) { - var pasteValue = CurrentContext.Request.Form["pasteValue"]; + var pasteValue = HttpContextAccessor.HttpContext!.Request.GetFormValue("pasteValue"); ImportInBackground(pasteValue); } @@ -300,7 +297,7 @@ private HtmlBuilder GetUploadAreaCollapse(string keyprocess) area.WithStyle( "display:none"); }); - var collapsePanel = new JJMasterDataCollapsePanel(CurrentContext.Request.Form) + var collapsePanel = new JJMasterDataCollapsePanel(HttpContextAccessor) { TitleIcon = new JJIcon(FontAwesomeIcon.Upload), Title = StringLocalizer["Upload File"], @@ -337,8 +334,7 @@ private HtmlBuilder GetUploadAreaCollapse(string keyprocess) private void FileUploaded(object sender, FormUploadFileEventArgs e) { var sb = new StringBuilder(); - Stream stream = new MemoryStream(e.File.Bytes); - using (var reader = new StreamReader(stream)) + using (var reader = new StreamReader(e.File.OpenReadStream())) { while (!reader.EndOfStream) { @@ -356,7 +352,7 @@ private void FileUploaded(object sender, FormUploadFileEventArgs e) private DataImportationWorker CreateImportationTextWorker(string postedText, char separator) { - var dataContext = new DataContext(CurrentContext.Request, DataContextSource.Upload, UserId); + var dataContext = new DataContext(HttpContextAccessor.HttpContext!.Request, DataContextSource.Upload, UserId); var dataImportationContext = new DataImportationContext(FormElement, dataContext, RelationValues, postedText, separator); var worker = DataImportationWorkerFactory.Create(dataImportationContext); worker.UserId = UserId; @@ -474,4 +470,4 @@ private JJUploadArea GetUploadArea() return area; } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Components/JsonComponentResult.cs b/src/MasterData.Core/UI/Components/JsonComponentResult.cs index bf5078e4d..205aff704 100644 --- a/src/MasterData.Core/UI/Components/JsonComponentResult.cs +++ b/src/MasterData.Core/UI/Components/JsonComponentResult.cs @@ -1,9 +1,7 @@ -#nullable enable using System.Text.Json; using JJMasterData.Commons.Serialization; #if NET using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; #endif diff --git a/src/MasterData.Core/UI/Components/ProcessComponent.cs b/src/MasterData.Core/UI/Components/ProcessComponent.cs index d53c7899d..0dc18dcf0 100644 --- a/src/MasterData.Core/UI/Components/ProcessComponent.cs +++ b/src/MasterData.Core/UI/Components/ProcessComponent.cs @@ -1,19 +1,18 @@ -using System.Collections.Generic; +#nullable disable warnings +using System.Collections.Generic; using System.Text; -using JJMasterData.Commons.Exceptions; using JJMasterData.Commons.Security.Cryptography.Abstractions; using JJMasterData.Commons.Tasks; using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.DataManager; using JJMasterData.Core.DataManager.Expressions; -using JJMasterData.Core.Http.Abstractions; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; namespace JJMasterData.Core.UI.Components; public abstract class ProcessComponent( - IHttpContext currentContext, + IHttpContextAccessor httpContextAccessor, IMasterDataUser masterDataUser, ExpressionsService expressionsService, IBackgroundTaskManager backgroundTaskManager, @@ -22,40 +21,34 @@ public abstract class ProcessComponent( IStringLocalizer stringLocalizer) : AsyncComponent { - private string _processKey; - private ProcessOptions _processOptions; - private string _userId; - internal ExpressionsService ExpressionsService { get; } = expressionsService; internal string ProcessKey { get { - if (string.IsNullOrEmpty(_processKey)) - _processKey = BuildProcessKey(); + if (string.IsNullOrEmpty(field)) + field = BuildProcessKey(); - return _processKey; + return field; } } - public Dictionary UserValues { get; set; } = new(); + public Dictionary UserValues { get; set; } = new(); /// /// Id do usuário Atual /// /// - /// Se a variavel não for atribuida diretamente, - /// o sistema tenta recuperar em UserValues ou nas variaveis de Sessão /// - internal string UserId => _userId ??= masterDataUser.Id; + internal string UserId => field ??= masterDataUser.Id; - public IHttpContext CurrentContext { get; init; } = currentContext; + public IHttpContextAccessor HttpContextAccessor { get; init; } = httpContextAccessor; public ProcessOptions ProcessOptions { - get => _processOptions ??= new ProcessOptions(); - set => _processOptions = value; + get => field ??= new ProcessOptions(); + set; } /// diff --git a/src/MasterData.Core/UI/Components/RedirectComponentResult.cs b/src/MasterData.Core/UI/Components/RedirectComponentResult.cs index c8ab28997..36464d66a 100644 --- a/src/MasterData.Core/UI/Components/RedirectComponentResult.cs +++ b/src/MasterData.Core/UI/Components/RedirectComponentResult.cs @@ -1,8 +1,6 @@ -#nullable enable using System.Threading.Tasks; #if NET -using Microsoft.AspNetCore.Mvc; #endif namespace JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Components/RenderedComponentResult.cs b/src/MasterData.Core/UI/Components/RenderedComponentResult.cs index 50235c312..ace14d1eb 100644 --- a/src/MasterData.Core/UI/Components/RenderedComponentResult.cs +++ b/src/MasterData.Core/UI/Components/RenderedComponentResult.cs @@ -1,5 +1,3 @@ -#nullable enable - using JJConsulting.Html; diff --git a/src/MasterData.Core/UI/Components/TabNav/JJMasterDataTabNav.cs b/src/MasterData.Core/UI/Components/TabNav/JJMasterDataTabNav.cs index f7a1bd8d2..6c5d473ce 100644 --- a/src/MasterData.Core/UI/Components/TabNav/JJMasterDataTabNav.cs +++ b/src/MasterData.Core/UI/Components/TabNav/JJMasterDataTabNav.cs @@ -1,20 +1,20 @@ using JJConsulting.Html.Bootstrap.Components; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Components; internal sealed class JJMasterDataTabNav : JJTabNav { - public JJMasterDataTabNav(IFormValues formValues) + public JJMasterDataTabNav(IHttpContextAccessor formValues) { - if (formValues.TryGetValue("selected_tab_" + Name, out var value)) + var request = formValues.HttpContext?.Request; + if (request?.HasFormContentType == true && + request.Form.TryGetValue("selected_tab_" + Name, out var value)) { - SelectedTabIndex = int.TryParse(value, out var intIndex) ? intIndex : 0; + SelectedTabIndex = int.TryParse(value.ToString(), out var intIndex) ? intIndex : 0; } else { SelectedTabIndex = 0; } } -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Events/Abstractions/GridEventHandlerBase.cs b/src/MasterData.Core/UI/Events/Abstractions/GridEventHandlerBase.cs index 4bdcb14bb..951f17792 100644 --- a/src/MasterData.Core/UI/Events/Abstractions/GridEventHandlerBase.cs +++ b/src/MasterData.Core/UI/Events/Abstractions/GridEventHandlerBase.cs @@ -1,6 +1,5 @@ using System.Threading.Tasks; -using JJMasterData.Core.Tasks; using JJMasterData.Core.UI.Events.Args; namespace JJMasterData.Core.UI.Events.Abstractions; @@ -8,11 +7,11 @@ namespace JJMasterData.Core.UI.Events.Abstractions; public abstract class GridEventHandlerBase : IGridEventHandler { public abstract string ElementName { get; } - public virtual ValueTask OnFilterLoadAsync(object sender, GridFilterLoadEventArgs eventArgs) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnRenderCellAsync(object sender, GridCellEventArgs eventArgs) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnRenderSelectedCellAsync(object sender, GridSelectedCellEventArgs eventArgs) => ValueTaskHelper.CompletedTask; + public virtual ValueTask OnFilterLoadAsync(object sender, GridFilterLoadEventArgs eventArgs) => ValueTask.CompletedTask; + public virtual void OnRenderCell(object? sender, GridCellEventArgs eventArgs) { } + public virtual void OnRenderSelectedCell(object? sender, GridSelectedCellEventArgs eventArgs) { } public virtual Task OnDataLoadAsync(object sender, GridDataLoadEventArgs eventArgs) => Task.CompletedTask; - public virtual ValueTask OnRenderActionAsync(object sender, ActionEventArgs eventArgs) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnRenderToolbarActionAsync(object sender, GridToolbarActionEventArgs eventArgs) => ValueTaskHelper.CompletedTask; - public virtual ValueTask OnRenderRowAsync(object sender, GridRowEventArgs eventArgs) => ValueTaskHelper.CompletedTask; + public virtual void OnRenderAction(object? sender, ActionEventArgs eventArgs) { } + public virtual void OnRenderToolbarAction(object? sender, GridToolbarActionEventArgs eventArgs) { } + public virtual void OnRenderRow(object? sender, GridRowEventArgs eventArgs) { } } diff --git a/src/MasterData.Core/UI/Events/Abstractions/IGridEventHandler.cs b/src/MasterData.Core/UI/Events/Abstractions/IGridEventHandler.cs index 53c4819f4..c43011d9a 100644 --- a/src/MasterData.Core/UI/Events/Abstractions/IGridEventHandler.cs +++ b/src/MasterData.Core/UI/Events/Abstractions/IGridEventHandler.cs @@ -15,19 +15,17 @@ public ValueTask OnFilterLoadAsync(object sender, GridFilterLoadEventArgs eventA ; #endif - public ValueTask OnRenderCellAsync(object sender, GridCellEventArgs eventArgs) + public void OnRenderCell(object? sender, GridCellEventArgs eventArgs) #if NET { - return ValueTask.CompletedTask; } #else ; #endif - public ValueTask OnRenderSelectedCellAsync(object sender, GridSelectedCellEventArgs eventArgs) + public void OnRenderSelectedCell(object? sender, GridSelectedCellEventArgs eventArgs) #if NET { - return ValueTask.CompletedTask; } #else ; @@ -41,28 +39,25 @@ public Task OnDataLoadAsync(object sender, GridDataLoadEventArgs eventArgs) #else ; #endif - public ValueTask OnRenderActionAsync(object sender, ActionEventArgs eventArgs) + public void OnRenderAction(object? sender, ActionEventArgs eventArgs) #if NET { - return ValueTask.CompletedTask; } #else ; #endif - ValueTask OnRenderToolbarActionAsync(object sender, GridToolbarActionEventArgs e) + void OnRenderToolbarAction(object? sender, GridToolbarActionEventArgs e) #if NET { - return ValueTask.CompletedTask; } #else ; #endif - ValueTask OnRenderRowAsync(object sender, GridRowEventArgs e) + void OnRenderRow(object? sender, GridRowEventArgs e) #if NET { - return ValueTask.CompletedTask; } #else ; #endif -} \ No newline at end of file +} diff --git a/src/MasterData.Core/UI/Events/Args/ActionEventArgs.cs b/src/MasterData.Core/UI/Events/Args/ActionEventArgs.cs index 358a1209d..11d8455bd 100644 --- a/src/MasterData.Core/UI/Events/Args/ActionEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/ActionEventArgs.cs @@ -2,18 +2,17 @@ using System.Collections.Generic; using JJConsulting.Html.Bootstrap.Components; using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.UI.Components; namespace JJMasterData.Core.UI.Events.Args; -public class ActionEventArgs(BasicAction action, JJLinkButton linkButton, Dictionary fieldValues) +public class ActionEventArgs(BasicAction action, JJLinkButton linkButton, Dictionary fieldValues) : EventArgs { public string ActionName { get; init; } = action.Name ?? throw new ArgumentNullException(nameof(action)); public JJLinkButton LinkButton { get; set; } = linkButton; - public Dictionary FieldValues { get; internal set; } = fieldValues; + public Dictionary FieldValues { get; internal set; } = fieldValues; - public string HtmlResult { get; set; } = null; + public string? HtmlResult { get; set; } } diff --git a/src/MasterData.Core/UI/Events/Args/FormDeleteFileEventArgs.cs b/src/MasterData.Core/UI/Events/Args/FormDeleteFileEventArgs.cs index 342de12b9..12e1f2073 100644 --- a/src/MasterData.Core/UI/Events/Args/FormDeleteFileEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/FormDeleteFileEventArgs.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; namespace JJMasterData.Core.UI.Events.Args; diff --git a/src/MasterData.Core/UI/Events/Args/FormDownloadFileEventArgs.cs b/src/MasterData.Core/UI/Events/Args/FormDownloadFileEventArgs.cs index 6daa88451..9057a3fd7 100644 --- a/src/MasterData.Core/UI/Events/Args/FormDownloadFileEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/FormDownloadFileEventArgs.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.IO; namespace JJMasterData.Core.UI.Events.Args; diff --git a/src/MasterData.Core/UI/Events/Args/FormRenameFileEventArgs.cs b/src/MasterData.Core/UI/Events/Args/FormRenameFileEventArgs.cs index d07c21bda..d161c07d3 100644 --- a/src/MasterData.Core/UI/Events/Args/FormRenameFileEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/FormRenameFileEventArgs.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; namespace JJMasterData.Core.UI.Events.Args; diff --git a/src/MasterData.Core/UI/Events/Args/FormUploadFileEventArgs.cs b/src/MasterData.Core/UI/Events/Args/FormUploadFileEventArgs.cs index 490e5f7fe..c4bb37725 100644 --- a/src/MasterData.Core/UI/Events/Args/FormUploadFileEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/FormUploadFileEventArgs.cs @@ -1,14 +1,14 @@ -using System; -using JJMasterData.Core.DataManager.IO; +#nullable disable warnings +using System; namespace JJMasterData.Core.UI.Events.Args; -public class FormUploadFileEventArgs(FormFileContent file) : EventArgs +public class FormUploadFileEventArgs(IFormFile file) : EventArgs { /// /// Arquivo recebido /// - public FormFileContent File { get; set; } = file; + public IFormFile File { get; set; } = file; /// /// Mensagem de erro referente a validação do evento (opcional) diff --git a/src/MasterData.Core/UI/Events/Args/GridCellEventEventArgs.cs b/src/MasterData.Core/UI/Events/Args/GridCellEventEventArgs.cs index 8ba22259c..6f153a696 100644 --- a/src/MasterData.Core/UI/Events/Args/GridCellEventEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/GridCellEventEventArgs.cs @@ -1,10 +1,8 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; using JJConsulting.Html; using JJConsulting.Html.Bootstrap.Abstractions; using JJMasterData.Core.DataDictionary.Models; -using JJMasterData.Core.UI.Components; namespace JJMasterData.Core.UI.Events.Args; diff --git a/src/MasterData.Core/UI/Events/Args/GridDataLoadEventArgs.cs b/src/MasterData.Core/UI/Events/Args/GridDataLoadEventArgs.cs index 8d482caa0..79e9380a1 100644 --- a/src/MasterData.Core/UI/Events/Args/GridDataLoadEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/GridDataLoadEventArgs.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.Collections.Generic; using JJMasterData.Commons.Data.Entity.Repository; diff --git a/src/MasterData.Core/UI/Events/Args/GridSelectedCellEventArgs.cs b/src/MasterData.Core/UI/Events/Args/GridSelectedCellEventArgs.cs index 6a004c572..86f8f028d 100644 --- a/src/MasterData.Core/UI/Events/Args/GridSelectedCellEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/GridSelectedCellEventArgs.cs @@ -1,4 +1,5 @@ -using System; +#nullable disable warnings +using System; using System.Collections.Generic; using JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Events/Args/GridToolbarActionEventArgs.cs b/src/MasterData.Core/UI/Events/Args/GridToolbarActionEventArgs.cs index 5b6783e37..1b17052d9 100644 --- a/src/MasterData.Core/UI/Events/Args/GridToolbarActionEventArgs.cs +++ b/src/MasterData.Core/UI/Events/Args/GridToolbarActionEventArgs.cs @@ -1,7 +1,7 @@ -using System; +#nullable disable warnings +using System; using JJConsulting.Html.Bootstrap.Components; using JJMasterData.Core.DataDictionary.Models.Actions; -using JJMasterData.Core.UI.Components; namespace JJMasterData.Core.UI.Events.Args; @@ -12,5 +12,5 @@ public class GridToolbarActionEventArgs(BasicAction action, JJLinkButton linkBut public JJLinkButton LinkButton { get; set; } = linkButton; - public string HtmlResult { get; set; } = null; + public string? HtmlResult { get; set; } = null; } diff --git a/src/MasterData.Core/UI/Events/GridEventHandlerResolver.cs b/src/MasterData.Core/UI/Events/GridEventHandlerResolver.cs index 0dfd3d7ac..673e5feba 100644 --- a/src/MasterData.Core/UI/Events/GridEventHandlerResolver.cs +++ b/src/MasterData.Core/UI/Events/GridEventHandlerResolver.cs @@ -1,3 +1,4 @@ +#nullable disable warnings using System; using JJMasterData.Core.Events.Abstractions; using JJMasterData.Core.UI.Events.Abstractions; diff --git a/src/MasterData.Core/UI/Routing/RouteContext.cs b/src/MasterData.Core/UI/Routing/RouteContext.cs index 569811638..5c610112c 100644 --- a/src/MasterData.Core/UI/Routing/RouteContext.cs +++ b/src/MasterData.Core/UI/Routing/RouteContext.cs @@ -1,5 +1,3 @@ -#nullable enable - using JJMasterData.Core.DataDictionary.Models; using JJMasterData.Core.UI.Components; diff --git a/src/MasterData.Core/UI/Routing/RouteContextFactory.cs b/src/MasterData.Core/UI/Routing/RouteContextFactory.cs index 864c94493..027613d3a 100644 --- a/src/MasterData.Core/UI/Routing/RouteContextFactory.cs +++ b/src/MasterData.Core/UI/Routing/RouteContextFactory.cs @@ -1,18 +1,18 @@ +#nullable disable warnings using JJMasterData.Commons.Security.Cryptography.Abstractions; -using JJMasterData.Core.Extensions; -using JJMasterData.Core.Http.Abstractions; namespace JJMasterData.Core.UI.Routing; -public class RouteContextFactory(IQueryString queryString, IEncryptionService encryptionService) +public class RouteContextFactory(IHttpContextAccessor httpContextAccessor, IEncryptionService encryptionService) { public RouteContext Create() { - if (queryString.TryGetValue("routeContext", out var encryptedQueryString)) + var queryString = httpContextAccessor.HttpContext?.Request.Query; + if (queryString?.TryGetValue("routeContext", out var encryptedQueryString) == true) { return encryptionService.DecryptRouteContext(encryptedQueryString); } return new RouteContext(); } -} \ No newline at end of file +} diff --git a/src/MasterData.Storage.Abstractions/FileStorageItem.cs b/src/MasterData.Storage.Abstractions/FileStorageItem.cs new file mode 100644 index 000000000..8d210f55f --- /dev/null +++ b/src/MasterData.Storage.Abstractions/FileStorageItem.cs @@ -0,0 +1,12 @@ +namespace JJConsulting.MasterData.Storage.Abstractions; + +public sealed class FileStorageItem +{ + public required string FolderPath { get; init; } + + public required string FileName { get; init; } + + public required long Length { get; init; } + + public required DateTime LastWriteTime { get; init; } +} diff --git a/src/MasterData.Storage.Abstractions/IFileStorage.cs b/src/MasterData.Storage.Abstractions/IFileStorage.cs new file mode 100644 index 000000000..7fecc8cab --- /dev/null +++ b/src/MasterData.Storage.Abstractions/IFileStorage.cs @@ -0,0 +1,11 @@ +namespace JJConsulting.MasterData.Storage.Abstractions; + +public interface IFileStorage +{ + Task> ListAsync(string folderPath, bool isRecursive = false, CancellationToken cancellationToken = default); + Task OpenReadAsync(string fullPath, CancellationToken cancellationToken = default); + Task SaveAsync(string fullPath, Stream content, bool replaceIfExists = true, CancellationToken cancellationToken = default); + Task DeleteAsync(string fullPath, CancellationToken cancellationToken = default); + Task DeleteFolderAsync(string folderPath, CancellationToken cancellationToken = default); + Task MoveAsync(string currentFullPath, string newFullPath, CancellationToken cancellationToken = default); +} diff --git a/src/MasterData.Storage.Abstractions/MasterData.Storage.Abstractions.csproj b/src/MasterData.Storage.Abstractions/MasterData.Storage.Abstractions.csproj new file mode 100644 index 000000000..5d9f739b4 --- /dev/null +++ b/src/MasterData.Storage.Abstractions/MasterData.Storage.Abstractions.csproj @@ -0,0 +1,37 @@ + + + + netstandard2.0 + enable + enable + 14 + + + + JJMasterData Storage Abstractions + JJMasterData Storage Abstractions + JJConsulting.MasterData.Storage.Abstractions + JJConsulting + Storage contracts and models for implementing pluggable file storage providers in JJMasterData applications. + jjmasterdata;storage;file-storage;abstractions;dependency-injection + GPL-3.0-only + false + https://github.com/JJConsulting/JJMasterData + git + JJConsulting.MasterData.Storage.Abstractions + JJConsulting.MasterData.Storage.Abstractions + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/src/MasterData.Web/Areas/DataDictionary/Controllers/ElementController.cs b/src/MasterData.Web/Areas/DataDictionary/Controllers/ElementController.cs index 456922e9e..85659c500 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Controllers/ElementController.cs +++ b/src/MasterData.Web/Areas/DataDictionary/Controllers/ElementController.cs @@ -86,14 +86,13 @@ private void ConfigureUploadArea(JJUploadArea upload) private async ValueTask FileUploaded(object? sender, FormUploadFileEventArgs e) { - await using var ms = new MemoryStream(e.File.Bytes); if (e.File.FileName.EndsWith(".zip")) { - await elementImportService.ImportZipFile(ms); + await elementImportService.ImportZipFile(e.File.OpenReadStream()); } else { - await elementImportService.Import(ms); + await elementImportService.Import(e.File.OpenReadStream()); } if (ModelState.IsValid) @@ -195,11 +194,11 @@ public async Task Delete() foreach (var elementName in elementNamesToDelete) { - await elementService.DeleteAsync(elementName); + await elementService.DeleteAsync(elementName!); } return RedirectToAction(nameof(Index)); } -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Areas/DataDictionary/Controllers/FieldController.cs b/src/MasterData.Web/Areas/DataDictionary/Controllers/FieldController.cs index c2d558449..82306a641 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Controllers/FieldController.cs +++ b/src/MasterData.Web/Areas/DataDictionary/Controllers/FieldController.cs @@ -100,7 +100,7 @@ public async Task Sort(string elementName, string fieldsOrder) } [HttpPost] - public async Task Copy(string elementName, FormElementField? field) + public async Task Copy(string elementName, FormElementField field) { var dictionary = await fieldService.GetFormElementAsync(elementName); await fieldService.CopyFieldAsync(dictionary, field); diff --git a/src/MasterData.Web/Areas/DataDictionary/Controllers/IndexesController.cs b/src/MasterData.Web/Areas/DataDictionary/Controllers/IndexesController.cs index 0c4052b2e..dcc6303ba 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Controllers/IndexesController.cs +++ b/src/MasterData.Web/Areas/DataDictionary/Controllers/IndexesController.cs @@ -57,7 +57,7 @@ public async Task Detail(string elementName, string? index, List CreateElementDetailsVie public async Task> GetPrimaryKeysSelectList(string elementName) { var formElement = await relationshipsService.GetFormElementAsync(elementName); - - var selectList = formElement.Fields - .Where(f=> f.IsPk) - .Select(field => new SelectListItem(field.Name, field.Name)) - .ToList(); + var selectList = formElement.Fields.ConvertAll(field => new SelectListItem(field.Name, field.Name)); return selectList; } diff --git a/src/MasterData.Web/Areas/DataDictionary/Controllers/RulesController.cs b/src/MasterData.Web/Areas/DataDictionary/Controllers/RulesController.cs new file mode 100644 index 000000000..0c51ee5c9 --- /dev/null +++ b/src/MasterData.Web/Areas/DataDictionary/Controllers/RulesController.cs @@ -0,0 +1,138 @@ +using JJMasterData.Core.DataDictionary.Models; +using JJMasterData.Core.DataDictionary.Services; +using JJMasterData.Web.Extensions; +using JJMasterData.Web.Filters; +using JJMasterData.Web.Models; +using Microsoft.AspNetCore.Mvc; +using System.Linq; + +namespace JJMasterData.Web.Areas.DataDictionary.Controllers; + +public class RulesController(FormElementRulesService formElementRulesService) : DataDictionaryController +{ + [ImportModelState] + public async Task Index(string elementName, int? ruleId = null) + { + var formElement = await formElementRulesService.GetFormElementAsync(elementName); + FormElementRule rule; + + if (ruleId == null) + { + if (TempData.ContainsKey("rule")) + rule = TempData.Get("rule")!; + else if (formElement.Rules.Count > 0) + rule = formElement.Rules[0]; + else + rule = new FormElementRule(); + } + else + { + rule = formElement.GetRuleById(ruleId.Value); + } + + PopulateViewData(formElement, rule); + return View(rule); + } + + public async Task Detail(string elementName, int ruleId) + { + var formElement = await formElementRulesService.GetFormElementAsync(elementName); + var rule = formElement.GetRuleById(ruleId); + PopulateViewData(formElement, rule); + return PartialView("_Detail", rule); + } + + public async Task Add(string elementName) + { + var formElement = await formElementRulesService.GetFormElementAsync(elementName); + var rule = new FormElementRule(); + PopulateViewData(formElement, rule); + return PartialView("_Detail", rule); + } + + [HttpPost] + public async Task ChangeLanguage(string elementName, FormElementRule rule) + { + var formElement = await formElementRulesService.GetFormElementAsync(elementName); + PopulateViewData(formElement, rule); + return PartialView("_Detail", rule); + } + + [HttpPost] + [ExportModelState] + public async Task Save(string elementName, FormElementRule rule, string selectedTab = "#div-general") + { + await formElementRulesService.SaveAsync(elementName, rule); + if (ModelState.IsValid) + return RedirectToAction("Index", new { elementName, ruleId = rule.Id, selectedTab }); + + return RedirectToIndex(elementName, rule, selectedTab); + } + + public async Task Delete(string elementName, int ruleId) + { + await formElementRulesService.DeleteAsync(elementName, ruleId); + return RedirectToAction("Index", new { elementName }); + } + + [HttpPost] + public async Task Index(string elementName, FormElementRule rule) + { + var formElement = await formElementRulesService.GetFormElementAsync(elementName); + PopulateViewData(formElement, rule); + return View(rule); + } + + private RedirectToActionResult RedirectToIndex(string elementName, FormElementRule rule, string selectedTab) + { + TempData.Put("rule", rule); + + return RedirectToAction("Index", new { elementName, selectedTab }); + } + + private void PopulateViewData(FormElement formElement, FormElementRule rule) + { + var selectedTab = Request.HasFormContentType + ? Request.Form["selectedTab"].ToString() + : Request.Query["selectedTab"].ToString(); + + ViewBag.Tab = string.IsNullOrWhiteSpace(selectedTab) ? "#div-general" : selectedTab; + ViewData["MenuId"] = "Rules"; + ViewData["ElementName"] = formElement.Name; + ViewData["CodeEditorHints"] = formElement.Fields.Select(f => new CodeEditorHint + { + Language = "sql", + InsertText = f.Name, + Label = f.Name, + Details = "Form Element Field", + }) + .Concat( + formElement.Fields.Select(f => new CodeEditorHint + { + Language = "javascript", + InsertText = $"values.{f.Name}", + Label = $"values.{f.Name}", + Details = "Form Element Field", + })) + .Concat( + [ + new CodeEditorHint + { + Language = "javascript", + InsertText = "addError('Mensagem de erro');", + Label = "addError(message)", + Details = "Adds a general error message", + }, + new CodeEditorHint + { + Language = "javascript", + InsertText = "addError('FieldName', 'Mensagem de erro');", + Label = "addError(name, message)", + Details = "Adds a field error", + }, + ]) + .ToList(); + ViewBag.RuleId = rule.Id; + ViewBag.Rules = formElement.Rules; + } +} diff --git a/src/MasterData.Web/Areas/DataDictionary/Models/RelationshipsElementDetailsViewModel.cs b/src/MasterData.Web/Areas/DataDictionary/Models/RelationshipsElementDetailsViewModel.cs index 374262b1c..71d150b27 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Models/RelationshipsElementDetailsViewModel.cs +++ b/src/MasterData.Web/Areas/DataDictionary/Models/RelationshipsElementDetailsViewModel.cs @@ -13,7 +13,7 @@ public sealed class RelationshipsElementDetailsViewModel public required List? ForeignKeysSelectList { get; set; } public required List? ElementsSelectList { get; set; } - [DisplayName("Primary Key Column")] + [DisplayName("Key Column")] public string? AddPrimaryKeyName { get; set; } [DisplayName("Foreign Key Column")] public string? AddForeignKeyName { get; set; } diff --git a/src/MasterData.Web/Areas/DataDictionary/Views/Actions/Index.cshtml b/src/MasterData.Web/Areas/DataDictionary/Views/Actions/Index.cshtml index 79a28e556..3e28fd38b 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Views/Actions/Index.cshtml +++ b/src/MasterData.Web/Areas/DataDictionary/Views/Actions/Index.cshtml @@ -162,7 +162,7 @@ const value = (input.value || "").toLowerCase(); const listSelector = "#sortable-" + source; $(listSelector + " a").filter(function () { - const textValues = $(this).clone().find(".bootstrap-select, .selectpicker, select").remove().end().text(); + const textValues = $(this).clone().find(".ts-wrapper, .tom-select, select").remove().end().text(); $(this).toggle(textValues.toLowerCase().indexOf(value) > -1); }); } diff --git a/src/MasterData.Web/Areas/DataDictionary/Views/Actions/_UrlRedirectAction.cshtml b/src/MasterData.Web/Areas/DataDictionary/Views/Actions/_UrlRedirectAction.cshtml index 468c2fa22..b7dd280b1 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Views/Actions/_UrlRedirectAction.cshtml +++ b/src/MasterData.Web/Areas/DataDictionary/Views/Actions/_UrlRedirectAction.cshtml @@ -28,23 +28,49 @@
+
+ +
- +
+ +
+
-
- -
+
- +
} + +@section Scripts { + +} diff --git a/src/MasterData.Web/Areas/DataDictionary/Views/Field/Index.cshtml b/src/MasterData.Web/Areas/DataDictionary/Views/Field/Index.cshtml index 75f8c1ff4..dbb38cf86 100644 --- a/src/MasterData.Web/Areas/DataDictionary/Views/Field/Index.cshtml +++ b/src/MasterData.Web/Areas/DataDictionary/Views/Field/Index.cshtml @@ -97,7 +97,7 @@ @if (isForm) { diff --git a/src/MasterData.Web/Configuration/Options/MasterDataWebOptions.cs b/src/MasterData.Web/Configuration/Options/MasterDataWebOptions.cs index 71c8d2f6d..b3c794304 100644 --- a/src/MasterData.Web/Configuration/Options/MasterDataWebOptions.cs +++ b/src/MasterData.Web/Configuration/Options/MasterDataWebOptions.cs @@ -31,8 +31,6 @@ public sealed class MasterDataWebOptions [Display(Name = "Custom Bootstrap Path")] public string? CustomBootstrapPath { get; set; } - public bool SupportNetFramework { get; set; } - /// /// Custom scripts to be added at _MasterDataScripts. The paths are relative. /// @@ -45,4 +43,4 @@ public sealed class MasterDataWebOptions ///
[BindNever] public List CustomStylesheetsPaths { get; } = []; -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Configuration/ServiceCollectionExtensions.cs b/src/MasterData.Web/Configuration/ServiceCollectionExtensions.cs index 5c9703774..b0d183c95 100644 --- a/src/MasterData.Web/Configuration/ServiceCollectionExtensions.cs +++ b/src/MasterData.Web/Configuration/ServiceCollectionExtensions.cs @@ -6,9 +6,7 @@ using JJMasterData.Web.Extensions; using JJMasterData.Web.Models; using JJMasterData.Web.Utils; -using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -95,12 +93,6 @@ private static void AddMasterDataWebServices( services.AddTransient(); services.AddHttpContextAccessor(); - services.AddSession(o => - { - o.Cookie.Name =".JJMasterData.Session"; - o.Cookie.IsEssential = true; - }); - services.AddMemoryCache(); services.AddActionFilters(); } @@ -122,4 +114,4 @@ private static void AddMvcServices( }; }); } -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Configuration/WebApplicationExtensions.cs b/src/MasterData.Web/Configuration/WebApplicationExtensions.cs index 687fb85cf..d00c066b3 100644 --- a/src/MasterData.Web/Configuration/WebApplicationExtensions.cs +++ b/src/MasterData.Web/Configuration/WebApplicationExtensions.cs @@ -1,11 +1,7 @@ -using System.Globalization; -using System.Text.RegularExpressions; using JetBrains.Annotations; using JJMasterData.Core.DataDictionary.Repository.Abstractions; using JJMasterData.Core.DataManager.Services; -using JJMasterData.Web.Configuration.Options; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.DependencyInjection; namespace JJMasterData.Web.Configuration; diff --git a/src/MasterData.Web/Filters/LookupParametersDecryptionFilter.cs b/src/MasterData.Web/Filters/LookupParametersDecryptionFilter.cs index 6724adc7a..1ab9e618f 100644 --- a/src/MasterData.Web/Filters/LookupParametersDecryptionFilter.cs +++ b/src/MasterData.Web/Filters/LookupParametersDecryptionFilter.cs @@ -26,7 +26,7 @@ public override void OnActionExecuting(ActionExecutingContext context) private void SetLookupParameters(ActionExecutingContext context, StringValues encryptedParameters) { - var lookupQueryString = encryptionService.DecryptStringWithUrlUnescape(encryptedParameters); + var lookupQueryString = encryptionService.DecryptString(encryptedParameters.ToString()); context.ActionArguments["lookupParameters"] = LookupParameters.FromQueryString(lookupQueryString); } } diff --git a/src/MasterData.Web/MasterData.Web.csproj b/src/MasterData.Web/MasterData.Web.csproj index f2e8ef212..7025bd839 100644 --- a/src/MasterData.Web/MasterData.Web.csproj +++ b/src/MasterData.Web/MasterData.Web.csproj @@ -14,7 +14,7 @@ JJMasterData.Web JJMasterData.Web true - false + import;global-builtin;if-function;color-functions wwwroot CompileTypeScript; @@ -27,7 +27,7 @@ - + @@ -35,6 +35,12 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + + + wwwroot/css/jjmasterdata/jjmasterdata.css + + @@ -44,12 +50,6 @@ Never - - Never - - - Never - diff --git a/src/MasterData.Web/Scripts/CodeEditor.ts b/src/MasterData.Web/Scripts/CodeEditor.ts index 8528595da..25d9c744b 100644 --- a/src/MasterData.Web/Scripts/CodeEditor.ts +++ b/src/MasterData.Web/Scripts/CodeEditor.ts @@ -58,6 +58,10 @@ class CodeEditor { return; } + if (!hints || typeof hints !== "object") { + return; + } + Object.keys(hints).forEach(lang => { //@ts-ignore monaco.languages.registerCompletionItemProvider(lang, { diff --git a/src/MasterData.Web/Scripts/GridViewFilterHelper.ts b/src/MasterData.Web/Scripts/GridViewFilterHelper.ts index 847c6ed93..2286028d1 100644 --- a/src/MasterData.Web/Scripts/GridViewFilterHelper.ts +++ b/src/MasterData.Web/Scripts/GridViewFilterHelper.ts @@ -50,8 +50,9 @@ class GridViewFilterHelper { currentObj.val("") } - if(currentObj.hasClass("selectpicker")){ - currentObj.selectpicker("val",""); + if(currentObj.hasClass("tom-select")){ + TomSelectHelper.clear(this as HTMLInputElement | HTMLSelectElement); + return; } if(currentObj.typeahead){ @@ -69,13 +70,9 @@ class GridViewFilterHelper { if (inputType == "checkbox") { currentObj.prop("checked", false); - } else if (inputType != "input" && currentObj.attr("data-role") == "tagsinput") { - currentObj.tagsinput('removeAll'); } else if (inputType != "hidden") { currentObj.val(null); - if (currentObj.hasClass("selectpicker")) { - currentObj.selectpicker("render"); - } else if (currentObj.hasClass("jj-search-box")) { + if (currentObj.hasClass("jj-search-box")) { // @ts-ignore currentObj[0].bootstrapSearch.clear(); } else if (currentObj.hasClass("jjlookup")) { @@ -114,6 +111,7 @@ class GridViewFilterHelper { success: (content) => { HTMLHelper.setOuterHTML(filterPanelName, content); listenAllEvents("#" + filterPanelName); + document.querySelector("#grid-view-filter-action-" + componentName).value = "clear"; GridViewHelper.refreshGrid(componentName, routeContext); document.getElementById(componentName + "-filter-icon").classList.add("d-none"); } @@ -130,7 +128,7 @@ class GridViewFilterHelper { const value = $(oDom).val().toString().toLowerCase(); $("#" + componentName + "-table" + " tr").filter(function () { //procura por textos - const textValues = $(this).clone().find('.bootstrap-select, .selectpicker, select').remove().end().text(); + const textValues = $(this).clone().find('.ts-wrapper, .tom-select, select').remove().end().text(); let isSearch = textValues.toLowerCase().indexOf(value) > -1; //se não achou procura nos inputs diff --git a/src/MasterData.Web/Scripts/JQueryPlugins.ts b/src/MasterData.Web/Scripts/JQueryPlugins.ts deleted file mode 100644 index dcdc8d0eb..000000000 --- a/src/MasterData.Web/Scripts/JQueryPlugins.ts +++ /dev/null @@ -1,8 +0,0 @@ -interface JQuery{ - selectpicker : Function - bootstrapToggle : Function - typeahead : Function - tagsinput : Function - valid: Function - sortable: Function -} \ No newline at end of file diff --git a/src/MasterData.Web/Scripts/ListenAllEvents.ts b/src/MasterData.Web/Scripts/ListenAllEvents.ts index 6d135b9b6..564680eac 100644 --- a/src/MasterData.Web/Scripts/ListenAllEvents.ts +++ b/src/MasterData.Web/Scripts/ListenAllEvents.ts @@ -1,10 +1,7 @@ const listenAllEvents = (selectorPrefix: string = String()) => { selectorPrefix += " " - $(selectorPrefix + ".selectpicker").selectpicker({ - iconBase: bootstrapVersion === 5 ? 'fa' : 'glyphicon', - styleBase: bootstrapVersion === 5 ? "form-select form-dropdown" : "form-control" - }); + TomSelectHelper.listen(selectorPrefix); if(bootstrapVersion === 3){ $(selectorPrefix + "input[type=checkbox][data-toggle^=toggle]").bootstrapToggle(); diff --git a/src/MasterData.Web/Scripts/PhoneInputListener.ts b/src/MasterData.Web/Scripts/PhoneInputListener.ts index 9a56778a6..d316fc274 100644 --- a/src/MasterData.Web/Scripts/PhoneInputListener.ts +++ b/src/MasterData.Web/Scripts/PhoneInputListener.ts @@ -28,7 +28,7 @@ class PhoneInputListener { } function syncHiddenInput(input: HTMLInputElement, select: HTMLSelectElement) { - const hiddenInput = $(input).closest('.input-group').find('.jj-phone-hidden-input')[0] as HTMLInputElement; + const hiddenInput = $(input).closest('.jj-phone-group').find('.jj-phone-hidden-input')[0] as HTMLInputElement; if (!hiddenInput) return; const selectedOption = select.selectedOptions[0]; @@ -40,15 +40,12 @@ class PhoneInputListener { const selects = document.querySelectorAll(`${selectorPrefix}select.jj-phone-select`); selects.forEach(select => { - $(select).on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) - { - if(isSelected){ - const input = $(select).closest('.input-group').find('.jj-phone-input')[0] as HTMLInputElement; - if (!input) return; + select.addEventListener('change', () => { + const input = $(select).closest('.input-group').find('.jj-phone-input')[0] as HTMLInputElement; + if (!input) return; - applyMask(input); - syncHiddenInput(input, select); - } + applyMask(input); + syncHiddenInput(input, select); }); }) @@ -58,7 +55,7 @@ class PhoneInputListener { const select = $(input).closest('.input-group').find('select.jj-phone-select')[0] as HTMLSelectElement; if (!select) return; - const hiddenInput = $(input).closest('.input-group').find('.jj-phone-hidden-input')[0] as HTMLInputElement; + const hiddenInput = $(input).closest('.jj-phone-group').find('.jj-phone-hidden-input')[0] as HTMLInputElement; const options = [...select.options]; const longestDialCode = options.reduce((longest, current) => { @@ -84,7 +81,7 @@ class PhoneInputListener { { const optionCountrySelected = getCountryFromInputValue(hiddenInput.value); if(optionCountrySelected) - $(select).selectpicker('val', optionCountrySelected.value); + TomSelectHelper.setValue(select, optionCountrySelected.value); } const selectedOption = select.selectedOptions[0] || options.find(option => option.value === $(select).val()); diff --git a/src/MasterData.Web/Scripts/TextFileHelper.ts b/src/MasterData.Web/Scripts/TextFileHelper.ts index ce8cf938c..48015ac9d 100644 --- a/src/MasterData.Web/Scripts/TextFileHelper.ts +++ b/src/MasterData.Web/Scripts/TextFileHelper.ts @@ -1,8 +1,9 @@ class TextFileHelper { - static showUploadView(fieldName: string, title: string, routeContext: string) { + static showUploadView(fieldName: string, title: string, routeContext: string, draftInputId: string) { const urlBuilder = new UrlBuilder(); urlBuilder.addQueryParameter("routeContext", routeContext) urlBuilder.addQueryParameter("fieldName", fieldName) + this.addDraftId(urlBuilder, draftInputId); const url = urlBuilder.build(); const modalId = fieldName + "-upload-modal"; @@ -21,10 +22,11 @@ class TextFileHelper { }) } - static refresh(fieldName: string, routeContext: string) { + static refresh(fieldName: string, routeContext: string, draftInputId: string) { const urlBuilder = new UrlBuilder(); urlBuilder.addQueryParameter("routeContext", routeContext) urlBuilder.addQueryParameter("fieldName", fieldName) + this.addDraftId(urlBuilder, draftInputId); const url = urlBuilder.build(); postFormValues({url:url,success:function(html){ @@ -47,4 +49,11 @@ class TextFileHelper { valueElement.value = valueText; } } -} \ No newline at end of file + + private static addDraftId(urlBuilder: UrlBuilder, draftInputId: string) { + const draftInput = document.getElementById(draftInputId) as HTMLInputElement; + if (draftInput?.value) { + urlBuilder.addQueryParameter("draftId", draftInput.value); + } + } +} diff --git a/src/MasterData.Web/Scripts/TomSelectHelper.ts b/src/MasterData.Web/Scripts/TomSelectHelper.ts new file mode 100644 index 000000000..29c999c84 --- /dev/null +++ b/src/MasterData.Web/Scripts/TomSelectHelper.ts @@ -0,0 +1,83 @@ +declare const TomSelect: any; + +type TomSelectElement = HTMLInputElement | HTMLSelectElement; + +class TomSelectHelper { + static listen(selectorPrefix = String()) { + document.querySelectorAll(`${selectorPrefix} select.tom-select, ${selectorPrefix} input.tom-select`) + .forEach(element => this.initialize(element)); + } + + static initialize(element: TomSelectElement) { + if ((element as any).tomselect) return (element as any).tomselect; + + const isTagsInput = element instanceof HTMLInputElement && element.dataset.tomSelectTags === 'true'; + const isMultiSelect = element instanceof HTMLSelectElement && element.multiple; + if (isTagsInput) + element.value = element.value + .split(',') + .map(value => value.trim()) + .filter(Boolean) + .join(','); + + const placeholder = element.dataset.placeholder + ?? element.getAttribute('placeholder') + ?? (element instanceof HTMLSelectElement + ? element.querySelector('option[value=""]')?.textContent?.trim() + : undefined) + ?? String(); + + return new TomSelect(element, { + allowEmptyOption: !isTagsInput, + hidePlaceholder: false, + hideSelected: false, + maxOptions: null, + placeholder, + ...(isTagsInput + ? { + create: true, + delimiter: ',' + } + : { + create: false, + controlInput: null, + plugins: isMultiSelect ? [ 'checkbox_options'] : [] + }), + render: { + no_results: () => `
${element.dataset.noResultsText ?? 'No results found.'}
`, + option: (data, escape) => this.renderOption(element, data, escape, true), + item: (data, escape) => this.renderOption(element, data, escape, false) + } + }); + } + + static destroy(element: TomSelectElement) { + (element as any).tomselect?.destroy(); + } + + static setValue(element: TomSelectElement, value: string | string[]) { + const tomSelect = this.initialize(element); + tomSelect.setValue(value); + } + + static clear(element: TomSelectElement) { + const tomSelect = this.initialize(element); + tomSelect.clear(); + } + + private static renderOption( + element: TomSelectElement, + data: any, + escape: (value: string) => string, + isDropdownItem: boolean) { + const option = element instanceof HTMLSelectElement + ? [...element.options].find(item => item.value === data.value) + : undefined; + const content = option?.dataset.content; + + const cssClass = isDropdownItem ? 'ts-option-content' : String(); + const itemContent = content ?? escape(data.text); + + return `
${itemContent}
`; + } +} diff --git a/src/MasterData.Web/Scripts/UploadAreaOptions.ts b/src/MasterData.Web/Scripts/UploadAreaOptions.ts index b801735d3..94a76c590 100644 --- a/src/MasterData.Web/Scripts/UploadAreaOptions.ts +++ b/src/MasterData.Web/Scripts/UploadAreaOptions.ts @@ -38,15 +38,17 @@ class UploadAreaOptions { const urlBuilder = new UrlBuilder(); urlBuilder.addQueryParameter("routeContext", routeContext) - const params = queryStringParams.split('&'); + const params = queryStringParams ? queryStringParams.split('&') : []; for (let i = 0; i < params.length; i++) { const param = params[i].split('='); const key = decodeURIComponent(param[0]); const value = decodeURIComponent(param[1]); - urlBuilder.addQueryParameter(key, value); + if (key) { + urlBuilder.addQueryParameter(key, value); + } } this.url = urlBuilder.build(); } } -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Scripts/UploadViewHelper.ts b/src/MasterData.Web/Scripts/UploadViewHelper.ts index 040ff1013..756c2e652 100644 --- a/src/MasterData.Web/Scripts/UploadViewHelper.ts +++ b/src/MasterData.Web/Scripts/UploadViewHelper.ts @@ -32,6 +32,32 @@ class UploadViewHelper { this.clearFileAction(componentName, fileName); } + static markDeleted(componentName: string, fileName: string, confirmationMessage: string, jsCallback: string, deletedInputId: string) { + if (confirmationMessage) { + const confirmed = confirm(confirmationMessage) + if (!confirmed) { + return + } + } + + const deletedInput = document.getElementById(deletedInputId) as HTMLInputElement; + if (!deletedInput) { + return; + } + + const deletedFiles = deletedInput.value + .split(",") + .map(value => value.trim()) + .filter(value => value.length > 0); + + if (deletedFiles.indexOf(fileName) === -1) { + deletedFiles.push(fileName); + deletedInput.value = deletedFiles.join(","); + } + + eval(jsCallback); + } + static downloadFile(componentName: string, fileName: string, jsCallback: string) { this.performFileAction(componentName, fileName, "downloadFile"); eval(jsCallback) @@ -39,9 +65,20 @@ class UploadViewHelper { } static renameFile(componentName: string, fileName: string, promptMessage: string, jsCallback: string) { - this.performFileAction(componentName, fileName, "renameFile", promptMessage); + const newName = prompt(promptMessage, fileName); + if (newName === null || newName === fileName) { + return; + } + + const uploadActionInput = document.getElementById("upload-view-action-" + componentName) as HTMLInputElement; + const filenameInput = document.getElementById("upload-view-file-name-" + componentName) as HTMLInputElement; + if (uploadActionInput && filenameInput) { + uploadActionInput.value = "renameFile"; + filenameInput.value = fileName + ";" + newName; + } + eval(jsCallback) this.clearFileAction(componentName,fileName); } -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Scripts/Vendors.d.ts b/src/MasterData.Web/Scripts/Vendors.d.ts new file mode 100644 index 000000000..1ebdc7523 --- /dev/null +++ b/src/MasterData.Web/Scripts/Vendors.d.ts @@ -0,0 +1,33 @@ +interface HTMLInputElement { + dropzone: any; +} + +interface Window { + Dropzone: any; +} + +declare const bootstrap: any; + +declare function flatpickr(selector: any, options?: any): any; + +declare const Dropzone: any; + +declare namespace Dropzone { + type DropzoneOptions = any; + type DropzoneFile = any; +} + +interface JQueryStatic { + (...args: any[]): any; + isFunction(value: any): boolean; +} + +declare const $: JQueryStatic; +declare const jQuery: JQueryStatic; + +interface JQuery{ + bootstrapToggle : Function + typeahead : Function + valid: Function + sortable: Function +} diff --git a/src/MasterData.Web/Styles/_accordion.scss b/src/MasterData.Web/Styles/_accordion.scss index e209344dc..c0d8217a6 100644 --- a/src/MasterData.Web/Styles/_accordion.scss +++ b/src/MasterData.Web/Styles/_accordion.scss @@ -1,7 +1,6 @@ @import "variables"; .accordion { - --bs-accordion-btn-active-icon: var(--bs-accordion-btn-icon); --bs-accordion-btn-focus-box-shadow: inset 0 calc(-1*var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color); } @@ -10,12 +9,10 @@ } .accordion-default { - --#{$prefix}accordion-active-bg: var(--bs-tertiary-bg) !important; - --#{$prefix}accordion-btn-active: var(--bs-tertiary-bg) !important; - --#{$prefix}accordion-btn-bg: var(--bs-tertiary-bg) !important; - --#{$prefix}accordion-active: var( --bs-body-color) !important; - --#{$prefix}accordion-active-color: var( --bs-body-color) !important; - --#{$prefix}accordion-btn-color: var( --bs-body-color) !important; + --#{$prefix}accordion-active-bg: transparent !important; + --#{$prefix}accordion-btn-bg: transparent !important; + --#{$prefix}accordion-active-color: var(--#{$prefix}accordion-color) !important; + --#{$prefix}accordion-btn-color: var(--#{$prefix}accordion-color) !important; } .accordion-primary { diff --git a/src/MasterData.Web/Styles/_form.scss b/src/MasterData.Web/Styles/_form.scss index ea2a8fa45..166dbda2a 100644 --- a/src/MasterData.Web/Styles/_form.scss +++ b/src/MasterData.Web/Styles/_form.scss @@ -68,10 +68,6 @@ a.disabled { } -.bootstrap-tagsinput { - width: 100%; -} - .required-symbol { color: red; } @@ -264,4 +260,4 @@ input.form-control:read-only { .alert-content{ font-size: 0.9rem; -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Styles/_tom-select.scss b/src/MasterData.Web/Styles/_tom-select.scss new file mode 100644 index 000000000..c15ba291c --- /dev/null +++ b/src/MasterData.Web/Styles/_tom-select.scss @@ -0,0 +1,706 @@ +@import "variables"; + + +/** + * Tom Select Bootstrap 5 + */ +/** + * tom-select.css (v2.6.2) + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at: + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + * + */ +.ts-control { + border: 1px solid var(--#{$prefix}border-color); + padding: $input-padding-y $input-padding-x; + width: 100%; + overflow: hidden; + position: relative; + z-index: 1; + box-sizing: border-box; + box-shadow: none; + border-radius: var(--#{$prefix}border-radius); + display: flex; + flex-wrap: wrap; +} +.ts-wrapper.multi.has-items .ts-control { + padding: calc(#{$input-padding-y} - 1px) $input-padding-x calc(#{$input-padding-y} - 4px); + min-height: calc(#{$input-line-height}em + #{$input-padding-y * 2}); +} +.full .ts-control { + background-color: var(--#{$prefix}body-bg); +} +.disabled .ts-control, .disabled .ts-control * { + cursor: default !important; +} +.ts-control > * { + vertical-align: baseline; + display: inline-block; +} +.ts-wrapper.multi .ts-control > div { + cursor: pointer; + margin: 0 3px 3px 0; + padding: 1px 5px; + background: var(--#{$prefix}secondary-bg); + color: var(--#{$prefix}body-color); + border: 0 solid var(--#{$prefix}border-color); + overflow: auto; +} +.ts-wrapper.multi .ts-control > div.active { + background: var(--#{$prefix}primary); + color: var(--#{$prefix}white); + border: 0 solid transparent; +} +.ts-wrapper.multi.disabled .ts-control > div, .ts-wrapper.multi.disabled .ts-control > div.active { + color: var(--#{$prefix}secondary-color); + background: var(--#{$prefix}secondary-bg); + border: 0 solid var(--#{$prefix}secondary-border-subtle); +} +.ts-control > input { + flex: 1 1 auto; + min-width: 7rem; + display: inline-block !important; + padding: 0 !important; + min-height: 0 !important; + max-height: none !important; + max-width: 100% !important; + margin: 0 !important; + text-indent: 0 !important; + border: 0 none !important; + background: none !important; + line-height: inherit !important; + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + -ms-user-select: auto !important; + user-select: auto !important; + box-shadow: none !important; +} +.ts-control > input::-ms-clear { + display: none; +} +.ts-control > input:focus { + outline: none !important; +} +.has-items .ts-control > input { + margin: 0px 4px !important; +} +.ts-control.rtl { + text-align: right; +} +.ts-control.rtl.single .ts-control:after { + left: calc(0.75rem + 5px); + right: auto; +} +.ts-control.rtl .ts-control > input { + margin: 0px 4px 0px -2px !important; +} +.disabled .ts-control { + opacity: 1; + background-color: var(--#{$prefix}secondary-bg); +} +.input-hidden .ts-control > input { + opacity: 0; + position: absolute; + left: -10000px; +} + +.ts-dropdown { + position: absolute; + top: 100%; + left: 0; + width: 100%; + z-index: 10; + border: 1px solid var(--#{$prefix}border-color); + background: var(--#{$prefix}body-bg); + margin: 0.25rem 0 0; + border-top: 0 none; + box-sizing: border-box; + border-radius: 0 0 var(--#{$prefix}border-radius) var(--#{$prefix}border-radius); +} +.ts-dropdown [data-selectable] { + cursor: pointer; + overflow: hidden; +} +.ts-dropdown [data-selectable] .highlight { + background: var(--#{$prefix}warning-bg-subtle); + border-radius: 1px; +} +.ts-dropdown .option, +.ts-dropdown .optgroup-header, +.ts-dropdown .no-results, +.ts-dropdown .create { + padding: var(--#{$prefix}dropdown-item-padding-y) var(--#{$prefix}dropdown-item-padding-x); +} +.ts-dropdown .option, .ts-dropdown [data-disabled], .ts-dropdown [data-disabled] [data-selectable].option { + cursor: inherit; + opacity: 0.5; +} +.ts-dropdown [data-selectable].option { + display: block; + width: 100%; + clear: both; + opacity: 1; + cursor: pointer; + color: var(--#{$prefix}dropdown-link-color, var(--#{$prefix}body-color)); + font-weight: var(--#{$prefix}dropdown-link-font-weight, 400); + white-space: nowrap; + background-color: transparent; + border: 0; +} +.ts-dropdown .optgroup:first-child .optgroup-header { + border-top: 0 none; +} +.ts-dropdown .optgroup-header { + color: var(--#{$prefix}secondary-color); + background: var(--#{$prefix}body-bg); + cursor: default; +} +.ts-dropdown [data-selectable].option.active, +.ts-dropdown [data-selectable].option.active:hover, +.ts-dropdown [data-selectable].option:focus { + background-color: var(--#{$prefix}primary); + color: var(--#{$prefix}white); +} +.ts-dropdown [data-selectable].option:hover { + background-color: var(--#{$prefix}primary-bg-subtle); + color: var(--#{$prefix}body-color); +} +.ts-dropdown [data-selectable].option.selected { + background-color: var(--#{$prefix}dropdown-link-active-bg, var(--#{$prefix}primary)); + color: var(--#{$prefix}dropdown-link-active-color, var(--#{$prefix}white)); +} +.ts-dropdown .active.create { + color: var(--#{$prefix}body-color); +} +.ts-dropdown .create { + color: var(--#{$prefix}secondary-color); +} +.ts-dropdown .spinner { + display: inline-block; + width: 30px; + height: 30px; + margin: 3px 0.75rem; +} +.ts-dropdown .spinner::after { + content: " "; + display: block; + width: 24px; + height: 24px; + margin: 3px; + border-radius: 50%; + border: 5px solid var(--#{$prefix}border-color); + border-color: var(--#{$prefix}border-color) transparent var(--#{$prefix}border-color) transparent; + animation: lds-dual-ring 1.2s linear infinite; +} +@keyframes lds-dual-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + + +.ts-dropdown-content { + max-height: 200px; + overflow-x: auto !important; + overflow-y: auto !important; + scroll-behavior: smooth; +} + +.ts-dropdown-content .option { + white-space: nowrap !important; + min-width: max-content !important; +} + +.ts-wrapper.tom-select-tags .ts-dropdown { + display: none !important; +} + +.ts-wrapper.plugin-drag_drop .ts-dragging { + color: transparent !important; +} +.ts-wrapper.plugin-drag_drop .ts-dragging > * { + visibility: hidden !important; +} + +.plugin-checkbox_options:not(.rtl) .option input { + margin-right: 0.5rem; +} + +.plugin-checkbox_options.rtl .option input { + margin-left: 0.5rem; +} + +/* stylelint-disable function-name-case */ +.plugin-clear_button { + --ts-pr-clear-button: 1em; +} +.plugin-clear_button .clear-button { + opacity: 0; + pointer-events: none; + position: absolute; + top: 50%; + transform: translateY(-50%); + right: calc(0.75rem - 5px); + margin-right: 0 !important; + background: transparent !important; + transition: opacity 0.5s; + cursor: pointer; +} +.plugin-clear_button.form-select .clear-button, .plugin-clear_button.single .clear-button { + right: max(var(--ts-pr-caret), 0.75rem); +} +.plugin-clear_button.focus.has-items .clear-button, .plugin-clear_button:not(.disabled):hover.has-items .clear-button { + opacity: 1; + pointer-events: auto; +} + +.ts-wrapper .dropdown-header { + position: relative; + padding: 6px 0.75rem; + border-bottom: 1px solid var(--#{$prefix}border-color); + background: color-mix(in srgb, var(--#{$prefix}body-bg) 85%, var(--#{$prefix}border-color)); + border-radius: var(--#{$prefix}border-radius) var(--#{$prefix}border-radius) 0 0; +} +.ts-wrapper .dropdown-header-close { + position: absolute; + right: 0.75rem; + top: 50%; + color: var(--#{$prefix}body-color); + opacity: 0.4; + margin-top: -12px; + line-height: 20px; + font-size: 20px !important; +} +.ts-wrapper .dropdown-header-close:hover { + color: var(--#{$prefix}body-color); +} + +.plugin-dropdown_input.focus.dropdown-active .ts-control { + border: 1px solid var(--#{$prefix}border-color); + box-shadow: var(--#{$prefix}box-shadow-inset); +} +.plugin-dropdown_input .dropdown-input { + border: 1px solid var(--#{$prefix}border-color); + border-width: 0 0 1px; + display: block; + padding: 0.375rem 0.75rem; + box-shadow: none; + width: 100%; + background: transparent; +} +.plugin-dropdown_input.focus .ts-dropdown .dropdown-input { + border-color: var(--#{$prefix}primary); + outline: 0; + box-shadow: 0 0 0 var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color); +} +.plugin-dropdown_input .items-placeholder { + border: 0 none !important; + box-shadow: none !important; + width: 100%; +} +.plugin-dropdown_input.has-items .items-placeholder, .plugin-dropdown_input.dropdown-active .items-placeholder { + display: none !important; +} + +.ts-wrapper.plugin-input_autogrow.has-items .ts-control > input { + min-width: 0; +} +.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control > input { + flex: none; + min-width: 4px; +} +.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control > input::-ms-input-placeholder { + color: transparent; +} +.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control > input::placeholder { + color: transparent; +} + +.ts-dropdown.plugin-optgroup_columns .ts-dropdown-content { + display: flex; +} +.ts-dropdown.plugin-optgroup_columns .optgroup { + border-right: 1px solid var(--#{$prefix}border-color); + border-top: 0 none; + flex-grow: 1; + flex-basis: 0; + min-width: 0; +} +.ts-dropdown.plugin-optgroup_columns .optgroup:last-child { + border-right: 0 none; +} +.ts-dropdown.plugin-optgroup_columns .optgroup::before { + display: none; +} +.ts-dropdown.plugin-optgroup_columns .optgroup-header { + border-top: 0 none; +} + +.ts-wrapper.plugin-remove_button .item { + display: inline-flex; + align-items: center; +} +.ts-wrapper.plugin-remove_button .item .remove { + color: inherit; + text-decoration: none; + vertical-align: middle; + display: inline-block; + padding: 0 5px; + border-radius: 0 2px 2px 0; + box-sizing: border-box; +} +.ts-wrapper.plugin-remove_button .item .remove:hover { + background: var(--#{$prefix}tertiary-bg); +} +.ts-wrapper.plugin-remove_button.disabled .item .remove:hover { + background: none; +} +.ts-wrapper.plugin-remove_button .remove-single { + position: absolute; + right: 0; + top: 0; + font-size: 23px; +} + +.ts-wrapper.plugin-remove_button:not(.rtl) .item { + padding-right: 0 !important; +} +.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove { + border-left: 1px solid var(--#{$prefix}border-color); + margin-left: 5px; +} +.ts-wrapper.plugin-remove_button:not(.rtl) .item.active .remove { + border-left-color: transparent; +} +.ts-wrapper.plugin-remove_button:not(.rtl).disabled .item .remove { + border-left-color: var(--#{$prefix}secondary-border-subtle); +} + +.ts-wrapper.plugin-remove_button.rtl .item { + padding-left: 0 !important; +} +.ts-wrapper.plugin-remove_button.rtl .item .remove { + border-right: 1px solid var(--#{$prefix}border-color); + margin-right: 5px; +} +.ts-wrapper.plugin-remove_button.rtl .item.active .remove { + border-right-color: transparent; +} +.ts-wrapper.plugin-remove_button.rtl.disabled .item .remove { + border-right-color: var(--#{$prefix}secondary-border-subtle); +} + +:root { + --ts-pr-clear-button: 0px; + --ts-pr-caret: 0px; + --ts-pr-min: .75rem; +} + +.ts-wrapper.single .ts-control, .ts-wrapper.single .ts-control input { + cursor: pointer; +} + +.ts-control:not(.rtl) { + padding-right: max(var(--ts-pr-min), var(--ts-pr-clear-button) + var(--ts-pr-caret)) !important; +} + +.ts-control.rtl { + padding-left: max(var(--ts-pr-min), var(--ts-pr-clear-button) + var(--ts-pr-caret)) !important; +} + +.ts-wrapper { + position: relative; +} + +.ts-dropdown, +.ts-control, +.ts-control input { + color: var(--#{$prefix}body-color); + font-family: inherit; + font-size: inherit; + line-height: $input-line-height; +} + +.ts-control, +.ts-wrapper.single.input-active .ts-control { + background: var(--#{$prefix}body-bg); + cursor: text; +} + +.ts-wrapper.tom-select:not(.tom-select-tags) .ts-control, +.ts-wrapper.tom-select:not(.tom-select-tags) .ts-control > input { + cursor: pointer; +} + +.ts-hidden-accessible { + border: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; +} + +.ts-dropdown, +.ts-dropdown.form-control, +.ts-dropdown.form-select { + // Use the same spacing and palette as a native .form-select popup: compact, + // full-width rows without Bootstrap dropdown-menu's inset appearance. + --#{$prefix}dropdown-item-padding-x: 0.75rem; + --#{$prefix}dropdown-item-padding-y: 0.375rem; + --#{$prefix}dropdown-link-color: var(--#{$prefix}body-color); + --#{$prefix}dropdown-link-hover-color: var(--#{$prefix}body-color); + --#{$prefix}dropdown-link-active-color: var(--#{$prefix}white); + --#{$prefix}dropdown-link-active-bg: var(--#{$prefix}primary); + height: auto; + padding: 0; + z-index: var(--#{$prefix}dropdown-zindex, 1000); + background: var(--#{$prefix}body-bg); + border: var(--#{$prefix}dropdown-border-width, var(--#{$prefix}border-width)) solid var(--#{$prefix}dropdown-border-color, var(--#{$prefix}border-color-translucent)); + border-radius: var(--#{$prefix}border-radius-lg); + box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.12); + overflow: hidden; +} + +.ts-dropdown .optgroup-header { + font-size: 0.875rem; + line-height: 1.5; +} +.ts-dropdown .optgroup:first-child::before { + display: none; +} +.ts-dropdown .optgroup::before { + content: " "; + display: block; + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid var(--#{$prefix}dropdown-divider-bg); + margin-left: -0.75rem; + margin-right: -0.75rem; +} +.ts-dropdown .create { + padding-left: 0.75rem; +} + +.ts-dropdown-content { + padding: 0; +} + +.ts-dropdown .ts-option-content { + display: flex; + align-items: center; + min-height: 1.5rem; +} + +.ts-control { + align-items: center; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .ts-control { + transition: none; + } +} +.focus:not(.form-control):not(.form-select) .ts-control { + border-color: var(--#{$prefix}primary); + outline: 0; + box-shadow: 0 0 0 var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color); +} +.ts-control .item { + display: flex; + align-items: center; +} +.ts-control input::-ms-input-placeholder { + color: var(--#{$prefix}secondary-color); + opacity: 1; +} +.ts-control input::placeholder { + color: var(--#{$prefix}secondary-color); + opacity: 1; +} + +@mixin validation-state($state) { + .ts-wrapper.is-#{$state}, + .was-validated .#{$state}, + .was-validated :#{$state} + .ts-wrapper { + border-color: var(--#{$prefix}form-#{$state}-border-color); + } + + .ts-wrapper.is-#{$state}:not(.single), + .was-validated .#{$state}:not(.single), + .was-validated :#{$state} + .ts-wrapper:not(.single) { + background-image: none; + } + + .ts-wrapper.is-#{$state}.single, + .was-validated .#{$state}.single, + .was-validated :#{$state} + .ts-wrapper.single { + background-image: var(--#{$prefix}form-select-bg-img); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px; + background-repeat: no-repeat; + } + + .ts-wrapper.is-#{$state}.focus .ts-control, + .was-validated .#{$state}.focus .ts-control, + .was-validated :#{$state} + .ts-wrapper.focus .ts-control { + border-color: var(--#{$prefix}form-#{$state}-border-color); + box-shadow: 0 0 0 var(--#{$prefix}focus-ring-width) color-mix(in srgb, var(--#{$prefix}form-#{$state}-color) 25%, transparent); + } +} + +@include validation-state(invalid); +@include validation-state(valid); + +.ts-wrapper { + min-height: calc(#{$input-line-height}em + #{$input-padding-y * 2} + calc(var(--#{$prefix}border-width) * 2)); + display: flex; +} +.input-group-sm > .ts-wrapper, .ts-wrapper.form-select-sm, .ts-wrapper.form-control-sm { + min-height: calc(#{$input-line-height}em + #{$input-padding-y-sm * 2} + calc(var(--#{$prefix}border-width) * 2)); +} +.input-group-sm > .ts-wrapper .ts-control, .ts-wrapper.form-select-sm .ts-control, .ts-wrapper.form-control-sm .ts-control { + padding: $input-padding-y-sm $input-padding-x-sm; + border-radius: var(--#{$prefix}border-radius-sm); + font-size: $input-font-size-sm; +} +.input-group-sm > .ts-wrapper.has-items .ts-control, .ts-wrapper.form-select-sm.has-items .ts-control, .ts-wrapper.form-control-sm.has-items .ts-control { + font-size: $input-font-size-sm; +} +.input-group-sm > .ts-wrapper.multi.has-items .ts-control, .ts-wrapper.form-select-sm.multi.has-items .ts-control, .ts-wrapper.form-control-sm.multi.has-items .ts-control { + padding-top: calc((calc(#{$input-line-height}em + #{$input-padding-y-sm * 2} + calc(var(--#{$prefix}border-width) * 2)) - #{$input-line-height * $input-font-size-sm} - calc((var(--#{$prefix}border-width) + 1px) * 2)) / 2) !important; +} +.ts-wrapper.multi.has-items .ts-control { + padding-left: calc(#{$input-padding-x} - 5px); + --ts-pr-min: calc(#{$input-padding-x} - 5px); +} +.ts-wrapper.multi .ts-control > div { + border-radius: calc(var(--#{$prefix}border-radius) - 1px); +} +.input-group-lg > .ts-wrapper, .ts-wrapper.form-control-lg, .ts-wrapper.form-select-lg { + min-height: calc(#{$input-line-height}em + #{$input-padding-y-lg * 2} + calc(var(--#{$prefix}border-width) * 2)); +} +.input-group-lg > .ts-wrapper .ts-control, .ts-wrapper.form-control-lg .ts-control, .ts-wrapper.form-select-lg .ts-control { + padding: $input-padding-y-lg $input-padding-x-lg; + border-radius: var(--#{$prefix}border-radius-lg); + font-size: $input-font-size-lg; +} +.ts-wrapper:not(.form-control, .form-select) { + padding: 0; + border: none; + height: auto; + box-shadow: none; + background: none; +} +.ts-wrapper:not(.form-control, .form-select).single .ts-control { + background-image: var(--#{$prefix}form-select-bg-img); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; +} +.ts-wrapper.form-select, .ts-wrapper.tom-select:not(.tom-select-tags), .ts-wrapper.single { + --ts-pr-caret: 2.25rem; +} +.ts-wrapper.form-control, .ts-wrapper.form-select { + padding: 0 !important; +} +.ts-wrapper.form-control .ts-control, .ts-wrapper.form-select .ts-control { + border: none !important; +} +.ts-wrapper.form-control:not(.disabled) .ts-control, .ts-wrapper.form-select:not(.disabled) .ts-control { + background: transparent !important; +} + +// Tom Select applies the Bootstrap form class to the wrapper, while its focus +// class is added to that same wrapper. Keep the border and ring on that outer +// element so they occupy the exact pixels used by .form-control/.form-select. +.ts-wrapper.form-control.focus, +.ts-wrapper.form-control:focus-within, +.ts-wrapper.form-select.focus, +.ts-wrapper.form-select:focus-within { + border-color: var(--#{$prefix}primary); + outline: 0; + box-shadow: 0 0 0 var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color); +} + +.ts-wrapper.form-control.disabled, +.ts-wrapper.form-select.disabled { + background-color: var(--#{$prefix}secondary-bg); +} + +.ts-wrapper.form-control.disabled .ts-control, +.ts-wrapper.form-select.disabled .ts-control { + background: transparent !important; +} + +.ts-wrapper.form-control.is-invalid.focus, +.ts-wrapper.form-control.is-invalid:focus-within, +.ts-wrapper.form-select.is-invalid.focus, +.ts-wrapper.form-select.is-invalid:focus-within { + border-color: var(--#{$prefix}form-invalid-border-color); + box-shadow: 0 0 0 var(--#{$prefix}focus-ring-width) color-mix(in srgb, var(--#{$prefix}form-invalid-color) 25%, transparent); +} + +.ts-wrapper.form-control.is-valid.focus, +.ts-wrapper.form-control.is-valid:focus-within, +.ts-wrapper.form-select.is-valid.focus, +.ts-wrapper.form-select.is-valid:focus-within { + border-color: var(--#{$prefix}form-valid-border-color); + box-shadow: 0 0 0 var(--#{$prefix}focus-ring-width) color-mix(in srgb, var(--#{$prefix}form-valid-color) 25%, transparent); +} + +.input-group > .ts-wrapper { + flex: 1 1 auto; + width: 1%; + min-width: 0; +} +.input-group > .ts-wrapper.w-auto { + // .form-select gives the wrapper width: 100%. An auto flex-basis then uses + // that full width and pushes the following input onto a new row. + flex: 0 1 max-content; + width: max-content !important; + max-width: 50%; +} +.input-group > .ts-wrapper.jj-phone-select, +.input-group > .ts-wrapper.jj-icon-select, +.input-group > .ts-wrapper.jj-phone-select > .ts-control, +.input-group > .ts-wrapper.jj-icon-select > .ts-control { + border-top-left-radius: var(--#{$prefix}border-radius) !important; + border-bottom-left-radius: var(--#{$prefix}border-radius) !important; +} +.input-group > .ts-wrapper:not(:first-child) { + margin-left: calc(var(--#{$prefix}border-width) * -1); + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group > .ts-wrapper:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group > .ts-wrapper.focus, +.input-group > .ts-wrapper:focus-within { + z-index: 5; +} + +.tomselect-checkbox{ + display: none +} + +.ts-wrapper.multi.disabled .ts-control .item { + background-color: var(--#{$prefix}tertiary-bg) !important; +} diff --git a/src/MasterData.Web/Styles/_variables.scss b/src/MasterData.Web/Styles/_variables.scss index 9c080ff9e..63ae58a4c 100644 --- a/src/MasterData.Web/Styles/_variables.scss +++ b/src/MasterData.Web/Styles/_variables.scss @@ -1 +1,13 @@ -$prefix: 'bs-' !default; \ No newline at end of file +$prefix: 'bs-' !default; + +$input-padding-y: 0.375rem !default; +$input-padding-x: 0.75rem !default; +$input-line-height: 1.5 !default; + +$input-padding-y-sm: 0.25rem !default; +$input-padding-x-sm: 0.5rem !default; +$input-font-size-sm: 0.875rem !default; + +$input-padding-y-lg: 0.5rem !default; +$input-padding-x-lg: 1rem !default; +$input-font-size-lg: 1.25rem !default; diff --git a/src/MasterData.Web/Styles/flags.scss b/src/MasterData.Web/Styles/flags.scss deleted file mode 100644 index 20d0fb294..000000000 --- a/src/MasterData.Web/Styles/flags.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import 'data-dictionary'; -@import 'sortable'; -@import 'modal'; -@import 'offcanvas'; -@import 'accordion'; -@import 'pagination'; -@import 'panel'; -@import 'search-box'; -@import 'card'; -@import 'form'; -@import 'spinner'; -@import 'switch'; -@import 'table'; -@import 'variables'; \ No newline at end of file diff --git a/src/MasterData.Web/Styles/jjmasterdata.scss b/src/MasterData.Web/Styles/jjmasterdata.scss index 20d0fb294..e9858e66e 100644 --- a/src/MasterData.Web/Styles/jjmasterdata.scss +++ b/src/MasterData.Web/Styles/jjmasterdata.scss @@ -11,4 +11,5 @@ @import 'spinner'; @import 'switch'; @import 'table'; +@import 'tom-select'; @import 'variables'; \ No newline at end of file diff --git a/src/MasterData.Web/TagHelpers/CheckboxTagHelper.cs b/src/MasterData.Web/TagHelpers/CheckboxTagHelper.cs index 1a8f8f3e6..d380c93b4 100644 --- a/src/MasterData.Web/TagHelpers/CheckboxTagHelper.cs +++ b/src/MasterData.Web/TagHelpers/CheckboxTagHelper.cs @@ -72,7 +72,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) if (ShowLabel) checkBox.Text = stringLocalizer[displayName ?? string.Empty]; - checkBox.Tooltip = Tooltip; + checkBox.Tooltip = Tooltip!; Configure?.Invoke(checkBox); output.TagName = null; diff --git a/src/MasterData.Web/Views/Shared/_MasterDataCodeEditorScripts.cshtml b/src/MasterData.Web/Views/Shared/_MasterDataCodeEditorScripts.cshtml index c0fe30d64..6874e2269 100644 --- a/src/MasterData.Web/Views/Shared/_MasterDataCodeEditorScripts.cshtml +++ b/src/MasterData.Web/Views/Shared/_MasterDataCodeEditorScripts.cshtml @@ -1,12 +1,12 @@ @{ Dictionary>? codeEditorHints = null; - if (ViewData.TryGetValue("CodeEditorHints", out var hintsObj) && hintsObj is List hintsList) + if (ViewData.TryGetValue("CodeEditorHints", out var hintsObj) && hintsObj is IEnumerable hintsEnumerable) { - codeEditorHints = hintsList + codeEditorHints = hintsEnumerable .GroupBy(h => h.Language) .ToDictionary(g => g.Key, g => g.ToList()); } } \ No newline at end of file + diff --git a/src/MasterData.Web/Views/Shared/_MasterDataScripts.cshtml b/src/MasterData.Web/Views/Shared/_MasterDataScripts.cshtml index c9d751181..4bfbc7986 100644 --- a/src/MasterData.Web/Views/Shared/_MasterDataScripts.cshtml +++ b/src/MasterData.Web/Views/Shared/_MasterDataScripts.cshtml @@ -34,7 +34,7 @@ break; } - + @@ -66,7 +66,6 @@ else } - @if (ViewData.ContainsKey("CodeEditorHints")) @@ -80,4 +79,4 @@ else @foreach (var customScriptPath in Options.Value.CustomScriptsPaths) { -} \ No newline at end of file +} diff --git a/src/MasterData.Web/Views/Shared/_MasterDataStylesheets.cshtml b/src/MasterData.Web/Views/Shared/_MasterDataStylesheets.cshtml index 784b79ec3..5e7bfedc2 100644 --- a/src/MasterData.Web/Views/Shared/_MasterDataStylesheets.cshtml +++ b/src/MasterData.Web/Views/Shared/_MasterDataStylesheets.cshtml @@ -20,13 +20,7 @@ else @if (BootstrapHelper.Version == 3) { - } -else -{ - -} - @@ -40,4 +34,4 @@ else { } - \ No newline at end of file + diff --git a/src/MasterData.Web/package-lock.json b/src/MasterData.Web/package-lock.json deleted file mode 100644 index be234ae8e..000000000 --- a/src/MasterData.Web/package-lock.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "name": "MasterData.Web", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "jquery-form": "^4.3.0", - "jquery-validation": "^1.20.0" - }, - "devDependencies": { - "@popperjs/core": "^2.11.5", - "@types/bootstrap": "^5.2.0", - "@types/dropzone": "^5.7.4", - "@types/jquery": "^3.5.14", - "flatpickr": "^4.6.13", - "jquery-ui": "^1.14.1" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.5", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", - "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@types/bootstrap": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.0.tgz", - "integrity": "sha512-zncxyEdbShnbOkY1zGBNqvpdVuIGDEA3rxcANJ4v9b3yaMxp+xDCNSwrXK5+uM7Wz7cb1RoIoRUQ0Q5JyfjyfA==", - "dev": true, - "dependencies": { - "@popperjs/core": "^2.9.2" - } - }, - "node_modules/@types/dropzone": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/@types/dropzone/-/dropzone-5.7.4.tgz", - "integrity": "sha512-9kLJ2YAmVRWYrHvDoa95pQzHF0HUMKcznsS7FM1Mht5Yieec+HMB6Ybfm+ocvLjvFCvgyYGFTp4nzNFxhZmo3g==", - "dev": true, - "dependencies": { - "@types/jquery": "*" - } - }, - "node_modules/@types/jquery": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", - "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", - "dev": true, - "dependencies": { - "@types/sizzle": "*" - } - }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, - "node_modules/flatpickr": { - "version": "4.6.13", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", - "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", - "dev": true - }, - "node_modules/jquery": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", - "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" - }, - "node_modules/jquery-form": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jquery-form/-/jquery-form-4.3.0.tgz", - "integrity": "sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ==", - "license": "(LGPL-2.1+ OR MIT)", - "dependencies": { - "jquery": ">=1.7.2" - } - }, - "node_modules/jquery-ui": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.1.tgz", - "integrity": "sha512-DhzsYH8VeIvOaxwi+B/2BCsFFT5EGjShdzOcm5DssWjtcpGWIMsn66rJciDA6jBruzNiLf1q0KvwMoX1uGNvnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "jquery": ">=1.12.0 <5.0.0" - } - }, - "node_modules/jquery-validation": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.20.0.tgz", - "integrity": "sha512-c8tg4ltIIP6L7l0bZ79sRzOJYquyjS48kQZ6iv8MJ2r0OYztxtkWYKTReZyU2/zVFYiINB29i0Z/IRNNuJQN1g==", - "license": "MIT", - "peerDependencies": { - "jquery": "^1.7 || ^2.0 || ^3.1" - } - } - }, - "dependencies": { - "@popperjs/core": { - "version": "2.11.5", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", - "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", - "dev": true - }, - "@types/bootstrap": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.0.tgz", - "integrity": "sha512-zncxyEdbShnbOkY1zGBNqvpdVuIGDEA3rxcANJ4v9b3yaMxp+xDCNSwrXK5+uM7Wz7cb1RoIoRUQ0Q5JyfjyfA==", - "dev": true, - "requires": { - "@popperjs/core": "^2.9.2" - } - }, - "@types/dropzone": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/@types/dropzone/-/dropzone-5.7.4.tgz", - "integrity": "sha512-9kLJ2YAmVRWYrHvDoa95pQzHF0HUMKcznsS7FM1Mht5Yieec+HMB6Ybfm+ocvLjvFCvgyYGFTp4nzNFxhZmo3g==", - "dev": true, - "requires": { - "@types/jquery": "*" - } - }, - "@types/jquery": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", - "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", - "dev": true, - "requires": { - "@types/sizzle": "*" - } - }, - "@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, - "flatpickr": { - "version": "4.6.13", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", - "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", - "dev": true - }, - "jquery": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", - "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" - }, - "jquery-form": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jquery-form/-/jquery-form-4.3.0.tgz", - "integrity": "sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ==", - "requires": { - "jquery": ">=1.7.2" - } - }, - "jquery-ui": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.1.tgz", - "integrity": "sha512-DhzsYH8VeIvOaxwi+B/2BCsFFT5EGjShdzOcm5DssWjtcpGWIMsn66rJciDA6jBruzNiLf1q0KvwMoX1uGNvnQ==", - "dev": true, - "requires": { - "jquery": ">=1.12.0 <5.0.0" - } - }, - "jquery-validation": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.20.0.tgz", - "integrity": "sha512-c8tg4ltIIP6L7l0bZ79sRzOJYquyjS48kQZ6iv8MJ2r0OYztxtkWYKTReZyU2/zVFYiINB29i0Z/IRNNuJQN1g==", - "requires": {} - } - } -} diff --git a/src/MasterData.Web/package.json b/src/MasterData.Web/package.json deleted file mode 100644 index b417b0b8d..000000000 --- a/src/MasterData.Web/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "devDependencies": { - "@popperjs/core": "^2.11.5", - "@types/bootstrap": "^5.2.0", - "@types/dropzone": "^5.7.4", - "@types/jquery": "^3.5.14", - "flatpickr": "^4.6.13", - "jquery-ui": "^1.14.1" - }, - "dependencies": { - "jquery-form": "^4.3.0", - "jquery-validation": "^1.20.0" - } -} diff --git a/src/MasterData.Web/sasscompiler.json b/src/MasterData.Web/sasscompiler.json deleted file mode 100644 index a183149d0..000000000 --- a/src/MasterData.Web/sasscompiler.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "Source": "Styles/jjmasterdata.scss", - "Target": "wwwroot/css/jjmasterdata/jjmasterdata.css", - "Arguments": "--style=compressed", - "IncludePaths": [], - "Configurations": { - "Debug": { - "Arguments": "--style=expanded" - } - } -} \ No newline at end of file diff --git a/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-select.css b/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-select.css deleted file mode 100644 index 4f1011860..000000000 --- a/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-select.css +++ /dev/null @@ -1,521 +0,0 @@ -/*! - * Bootstrap-select v1.14.0-beta3 (https://developer.snapappointments.com/bootstrap-select) - * - * Copyright 2012-2022 SnapAppointments, LLC - * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) - */ - -@-webkit-keyframes bs-notify-fadeOut { - 0% { - opacity: .9 - } - - 100% { - opacity: 0 - } -} - -@-o-keyframes bs-notify-fadeOut { - 0% { - opacity: .9 - } - - 100% { - opacity: 0 - } -} - -@keyframes bs-notify-fadeOut { - 0% { - opacity: .9 - } - - 100% { - opacity: 0 - } -} - -.bootstrap-select > select.bs-select-hidden, select.bs-select-hidden, select.selectpicker { - display: none !important -} - -.bootstrap-select { - width: 220px; - vertical-align: middle -} - - .bootstrap-select > .dropdown-toggle { - position: relative; - width: 100%; - text-align: right; - white-space: nowrap; - display: -webkit-inline-box; - display: -webkit-inline-flex; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between - } - - .bootstrap-select > .dropdown-toggle:after { - margin-top: -1px - } - - .bootstrap-select > .dropdown-toggle.bs-placeholder, .bootstrap-select > .dropdown-toggle.bs-placeholder:active, .bootstrap-select > .dropdown-toggle.bs-placeholder:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder:hover { - color: #999 - } - - .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus, .bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover { - color: rgba(255,255,255,.5) - } - - .bootstrap-select > select { - position: absolute !important; - bottom: 0; - left: 50%; - display: block !important; - width: .5px !important; - height: 100% !important; - padding: 0 !important; - opacity: 0 !important; - border: none; - z-index: 0 !important - } - - .bootstrap-select > select.mobile-device { - top: 0; - left: 0; - display: block !important; - width: 100% !important; - z-index: 2 !important - } - - .bootstrap-select.is-invalid .dropdown-toggle, .error .bootstrap-select .dropdown-toggle, .has-error .bootstrap-select .dropdown-toggle, .was-validated .bootstrap-select select:invalid + .dropdown-toggle { - border-color: #b94a48 - } - - .bootstrap-select.is-valid .dropdown-toggle, .was-validated .bootstrap-select select:valid + .dropdown-toggle { - border-color: #28a745 - } - - .bootstrap-select.fit-width { - width: auto !important - } - - .bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn) { - width: 220px - } - - .bootstrap-select .dropdown-toggle:focus, .bootstrap-select > select.mobile-device:focus + .dropdown-toggle { - outline: thin dotted #333 !important; - outline: 5px auto -webkit-focus-ring-color !important; - outline-offset: -2px - } - - .bootstrap-select.form-control { - margin-bottom: 0; - padding: 0; - border: none; - height: auto - } - -:not(.input-group) > .bootstrap-select.form-control:not([class*=col-]) { - width: 100% -} - -.bootstrap-select.form-control.input-group-btn { - float: none; - z-index: auto -} - -.form-inline .bootstrap-select, .form-inline .bootstrap-select.form-control:not([class*=col-]) { - width: auto -} - -.bootstrap-select:not(.input-group-btn), .bootstrap-select[class*=col-] { - float: none; - display: inline-block; - margin-left: 0 -} - - .bootstrap-select.dropdown-menu-right, .bootstrap-select[class*=col-].dropdown-menu-right, .row .bootstrap-select[class*=col-].dropdown-menu-right { - float: right - } - -.form-group .bootstrap-select, .form-horizontal .bootstrap-select, .form-inline .bootstrap-select { - margin-bottom: 0 -} - -.form-group-lg .bootstrap-select.form-control, .form-group-sm .bootstrap-select.form-control { - padding: 0 -} - - .form-group-lg .bootstrap-select.form-control .dropdown-toggle, .form-group-sm .bootstrap-select.form-control .dropdown-toggle { - height: 100%; - font-size: inherit; - line-height: inherit; - border-radius: inherit - } - -.bootstrap-select.form-control-lg .dropdown-toggle, .bootstrap-select.form-control-sm .dropdown-toggle { - font-size: inherit; - line-height: inherit; - border-radius: inherit -} - -.bootstrap-select.form-control-sm .dropdown-toggle { - padding: .25rem .5rem -} - -.bootstrap-select.form-control-lg .dropdown-toggle { - padding: .5rem 1rem -} - -.form-inline .bootstrap-select .form-control { - width: 100% -} - -.bootstrap-select.disabled, .bootstrap-select > .disabled { - cursor: not-allowed -} - - .bootstrap-select.disabled:focus, .bootstrap-select > .disabled:focus { - outline: 0 !important - } - -.bootstrap-select.bs-container { - position: absolute; - top: 0; - left: 0; - height: 0 !important; - padding: 0 !important -} - - .bootstrap-select.bs-container .dropdown-menu { - z-index: 1060 - } - -.bootstrap-select .dropdown-toggle .filter-option { - position: static; - top: 0; - left: 0; - float: left; - height: 100%; - width: 100%; - text-align: left; - overflow: hidden; - -webkit-box-flex: 0; - -webkit-flex: 0 1 auto; - -ms-flex: 0 1 auto; - flex: 0 1 auto -} - -.bs3.bootstrap-select .dropdown-toggle .filter-option { - padding-right: inherit -} - -.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option { - position: absolute; - padding-top: inherit; - padding-bottom: inherit; - padding-left: inherit; - float: none -} - - .input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner { - padding-right: inherit - } - -.bootstrap-select .dropdown-toggle .filter-option-inner-inner { - overflow: hidden -} - -.bootstrap-select .dropdown-toggle .filter-expand { - width: 0 !important; - float: left; - opacity: 0 !important; - overflow: hidden -} - -.bootstrap-select .dropdown-toggle .caret { - position: absolute; - top: 50%; - right: 12px; - margin-top: -2px; - vertical-align: middle -} - -.bootstrap-select .dropdown-toggle .bs-select-clear-selected { - position: relative; - display: block; - margin-right: 5px; - text-align: center -} - -.bs3.bootstrap-select .dropdown-toggle .bs-select-clear-selected { - padding-right: inherit -} - -.bootstrap-select .dropdown-toggle .bs-select-clear-selected span { - position: relative; - top: -webkit-calc(((-1em / 1.5) + 1ex)/ 2); - top: calc(((-1em / 1.5) + 1ex)/ 2); - pointer-events: none -} - -.bs3.bootstrap-select .dropdown-toggle .bs-select-clear-selected span { - top: auto -} - -.bootstrap-select .dropdown-toggle.bs-placeholder .bs-select-clear-selected { - display: none -} - -.input-group .bootstrap-select.form-control .dropdown-toggle { - border-radius: inherit -} - -.bootstrap-select[class*=col-] .dropdown-toggle { - width: 100% -} - -.bootstrap-select .dropdown-menu { - min-width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - - .bootstrap-select .dropdown-menu > .inner:focus { - outline: 0 !important - } - - .bootstrap-select .dropdown-menu.inner { - position: static; - float: none; - border: 0; - padding: 0; - margin: 0; - border-radius: 0; - -webkit-box-shadow: none; - box-shadow: none - } - - .bootstrap-select .dropdown-menu li { - position: relative - } - - .bootstrap-select .dropdown-menu li.active small { - color: rgba(255,255,255,.5) !important - } - - .bootstrap-select .dropdown-menu li.disabled a { - cursor: not-allowed - } - - .bootstrap-select .dropdown-menu li a { - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none - } - - .bootstrap-select .dropdown-menu li a.opt { - position: relative; - padding-left: 2.25em - } - - .bootstrap-select .dropdown-menu li a span.check-mark { - display: none - } - - .bootstrap-select .dropdown-menu li a span.text { - display: inline-block - } - - .bootstrap-select .dropdown-menu li small { - padding-left: .5em - } - - .bootstrap-select .dropdown-menu .notify { - position: absolute; - bottom: 5px; - width: 96%; - margin: 0 2%; - min-height: 26px; - padding: 3px 5px; - background: #f5f5f5; - border: 1px solid #e3e3e3; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05); - box-shadow: inset 0 1px 1px rgba(0,0,0,.05); - pointer-events: none; - opacity: .9; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box - } - - .bootstrap-select .dropdown-menu .notify.fadeOut { - -webkit-animation: .3s linear 750ms forwards bs-notify-fadeOut; - -o-animation: .3s linear 750ms forwards bs-notify-fadeOut; - animation: .3s linear 750ms forwards bs-notify-fadeOut - } - -.bootstrap-select .no-results { - padding: 3px; - background: #f5f5f5; - margin: 0 5px; - white-space: nowrap -} - -.bootstrap-select.fit-width .dropdown-toggle .filter-option { - position: static; - display: inline; - padding: 0 -} - -.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner, .bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner { - display: inline -} - -.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before { - content: '\00a0' -} - -.bootstrap-select.fit-width .dropdown-toggle .caret { - position: static; - top: auto; - margin-top: -1px -} - -.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark { - position: absolute; - display: inline-block; - right: 15px; - top: 5px -} - -.bootstrap-select.show-tick .dropdown-menu li a span.text { - margin-right: 34px -} - -.bootstrap-select .bs-ok-default:after { - content: ''; - display: block; - width: .5em; - height: 1em; - border-style: solid; - border-width: 0 .26em .26em 0; - -webkit-transform-style: preserve-3d; - transform-style: preserve-3d; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - -o-transform: rotate(45deg); - transform: rotate(45deg) -} - -.bootstrap-select.show-menu-arrow.open > .dropdown-toggle, .bootstrap-select.show-menu-arrow.show > .dropdown-toggle { - z-index: 1061 -} - -.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before { - content: ''; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid rgba(204,204,204,.2); - position: absolute; - bottom: -4px; - left: 9px; - display: none -} - -.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after { - content: ''; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #fff; - position: absolute; - bottom: -4px; - left: 10px; - display: none -} - -.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before { - bottom: auto; - top: -4px; - border-top: 7px solid rgba(204,204,204,.2); - border-bottom: 0 -} - -.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after { - bottom: auto; - top: -4px; - border-top: 6px solid #fff; - border-bottom: 0 -} - -.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before { - right: 12px; - left: auto -} - -.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after { - right: 13px; - left: auto -} - -.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after, .bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before, .bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after, .bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before { - display: block -} - -.bs-actionsbox, .bs-donebutton, .bs-searchbox { - padding: 4px 8px -} - -.bs-actionsbox { - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - - .bs-actionsbox .btn-group { - display: block - } - - .bs-actionsbox .btn-group button { - width: 50% - } - -.bs-donebutton { - float: left; - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - - .bs-donebutton .btn-group { - display: block - } - - .bs-donebutton .btn-group button { - width: 100% - } - -.bs-searchbox + .bs-actionsbox { - padding: 0 8px 4px -} - -.bs-searchbox .form-control { - margin-bottom: 0; - width: 100%; - float: none -} diff --git a/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-tagsinput-bs5.css b/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-tagsinput-bs5.css deleted file mode 100644 index bf925b5d3..000000000 --- a/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-tagsinput-bs5.css +++ /dev/null @@ -1,61 +0,0 @@ -.bootstrap-tagsinput { - display: block; - width: 100%; - padding: .375rem .75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: var(--bs-body-color) !important; - appearance: none; - background-color: var(--bs-body-bg) !important; - background-clip: padding-box; - border: var(--bs-border-width) solid var(--bs-border-color) !important; - border-radius: var(--bs-border-radius) !important; - transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; -} - -.bootstrap-tagsinput:focus-within { - color: var(--bs-body-color) !important; - background-color: var(--bs-body-bg) !important; - border-color: var(--bs-primary-border-subtle) !important; - outline: 0; - box-shadow: 0 0 0 .25rem rgba(var(--bs-primary-rgb),.25) !important; -} - -.bootstrap-tagsinput input { - border: none; - box-shadow: none; - outline: none; - background-color: transparent; - padding: 0 6px; - margin: 0; - width: auto; - max-width: inherit; -} - -.bootstrap-tagsinput.form-control input::-moz-placeholder { - color: #777; - opacity: 1; -} -.bootstrap-tagsinput.form-control input:-ms-input-placeholder { - color: #777; -} -.bootstrap-tagsinput.form-control input::-webkit-input-placeholder { - color: #777; -} -.bootstrap-tagsinput input:focus { - border: none; - box-shadow: none; -} -.bootstrap-tagsinput .tag { - margin-right: 2px; - color: white; -} -.bootstrap-tagsinput .tag [data-role="remove"] { - margin-left: 8px; - cursor: pointer; -} -.bootstrap-tagsinput .tag [data-role="remove"]:after { - content: "x"; - padding: 0px 2px; -} diff --git a/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-tagsinput.css b/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-tagsinput.css deleted file mode 100644 index abd8d8bb7..000000000 --- a/src/MasterData.Web/wwwroot/css/bootstrap/bootstrap-tagsinput.css +++ /dev/null @@ -1,59 +0,0 @@ -.bootstrap-tagsinput { - background-color: #fff; - border: 1px solid #ccc; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - display: inline-block; - padding: 4px 6px; - color: #555; - vertical-align: middle; - border-radius: 4px; - max-width: 100%; - line-height: 22px; - cursor: text; -} -.bootstrap-tagsinput input { - border: none; - box-shadow: none; - outline: none; - background-color: transparent; - padding: 0 6px; - margin: 0; - width: auto; - max-width: inherit; -} -.bootstrap-tagsinput.form-control input::-moz-placeholder { - color: #777; - opacity: 1; -} -.bootstrap-tagsinput.form-control input:-ms-input-placeholder { - color: #777; -} -.bootstrap-tagsinput.form-control input::-webkit-input-placeholder { - color: #777; -} -.bootstrap-tagsinput input:focus { - border: none; - box-shadow: none; -} -.bootstrap-tagsinput .tag { - margin-right: 2px; - color: white; -} -.bootstrap-tagsinput .tag [data-role="remove"] { - margin-left: 8px; - cursor: pointer; -} -.bootstrap-tagsinput .tag [data-role="remove"]:after { - content: "x"; - padding: 0px 2px; -} -.bootstrap-tagsinput .tag [data-role="remove"]:hover { - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.bootstrap-tagsinput .tag [data-role="remove"]:hover:active { - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} - -.label-info { - background-color: #113684 !important; -} \ No newline at end of file diff --git a/src/MasterData.Web/wwwroot/js/bootstrap/bootstrap-select/bootstrap-select.min.js b/src/MasterData.Web/wwwroot/js/bootstrap/bootstrap-select/bootstrap-select.min.js deleted file mode 100644 index 461e48099..000000000 --- a/src/MasterData.Web/wwwroot/js/bootstrap/bootstrap-select/bootstrap-select.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap-select v1.14.0-beta3 (https://developer.snapappointments.com/bootstrap-select) - * - * Copyright 2012-2022 SnapAppointments, LLC - * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) - */ -!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){!function($){"use strict";var M=["sanitize","whiteList","sanitizeFn"],W=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],P={"*":["class","dir","id","lang","role","tabindex","style",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},B=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,R=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i,U=["title","placeholder"];function S(e,t,i){if(i&&"function"==typeof i)return i(e);for(var s=Object.keys(t),n=0,o=e.length;n]+>/g,"")),a=(a=s?u(a):a).toUpperCase(),o="function"==typeof i?i(a,t):"contains"===i?0<=a.indexOf(t):a.startsWith(t)))break}return o}function v(e){return parseInt(e,10)||0}$.fn.triggerNative=function(e){var t,i=this[0];i.dispatchEvent&&(V?t=new Event(e,{bubbles:!0}):(t=document.createEvent("Event")).initEvent(e,!0,!1),i.dispatchEvent(t))};var j={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"},_=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,F=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\u1ab0-\\u1aff\\u1dc0-\\u1dff]","g");function G(e){return j[e]}function u(e){return(e=e.toString())&&e.replace(_,G).replace(F,"")}f={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},s="(?:"+Object.keys(f).join("|")+")",q=RegExp(s),K=RegExp(s,"g");var f,q,K,k=function(e){return q.test(e=null==e?"":""+e)?e.replace(K,Q):e};function Q(e){return f[e]}var Y={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},Z=27,J=13,w=32,I=9,C=38,O=40,m=window.Dropdown||bootstrap.Dropdown;function X(){var t;try{t=$.fn.dropdown.Constructor.VERSION}catch(e){t=m.VERSION}return t}var g={success:!1,major:"3"};try{g.full=(X()||"").split(" ")[0].split("."),g.major=g.full[0],g.success=!0}catch(e){}var ee=0,A=".bs.select",T={DISABLED:"disabled",DIVIDER:"divider",SHOW:"open",DROPUP:"dropup",MENU:"dropdown-menu",MENURIGHT:"dropdown-menu-right",MENULEFT:"dropdown-menu-left",BUTTONCLASS:"btn-default",POPOVERHEADER:"popover-title",ICONBASE:"glyphicon",TICKICON:"glyphicon-ok"},z={MENU:"."+T.MENU,DATA_TOGGLE:'data-toggle="dropdown"'},D={div:document.createElement("div"),span:document.createElement("span"),i:document.createElement("i"),subtext:document.createElement("small"),a:document.createElement("a"),li:document.createElement("li"),whitespace:document.createTextNode("\xa0"),fragment:document.createDocumentFragment(),option:document.createElement("option")},te=(D.selectedOption=D.option.cloneNode(!1),D.selectedOption.setAttribute("selected",!0),D.noResults=D.li.cloneNode(!1),D.noResults.className="no-results",D.a.setAttribute("role","option"),D.a.className="dropdown-item",D.subtext.className="text-muted",D.text=D.span.cloneNode(!1),D.text.className="text",D.checkMark=D.span.cloneNode(!1),new RegExp(C+"|"+O)),ie=new RegExp("^"+I+"$|"+Z),L={li:function(e,t,i){var s=D.li.cloneNode(!1);return e&&(1===e.nodeType||11===e.nodeType?s.appendChild(e):s.innerHTML=e),void 0!==t&&""!==t&&(s.className=t),null!=i&&s.classList.add("optgroup-"+i),s},a:function(e,t,i){var s=D.a.cloneNode(!0);return e&&(11===e.nodeType?s.appendChild(e):s.insertAdjacentHTML("beforeend",e)),void 0!==t&&""!==t&&s.classList.add.apply(s.classList,t.split(/\s+/)),i&&s.setAttribute("style",i),s},text:function(e,t){var i,s,n=D.text.cloneNode(!1);if(e.content?n.innerHTML=e.content:(n.textContent=e.text,e.icon&&(i=D.whitespace.cloneNode(!1),(s=(!0===t?D.i:D.span).cloneNode(!1)).className=this.options.iconBase+" "+e.icon,D.fragment.appendChild(s),D.fragment.appendChild(i)),e.subtext&&((s=D.subtext.cloneNode(!1)).textContent=e.subtext,n.appendChild(s))),!0===t)for(;0'},maxOptions:!1,mobile:!1,selectOnTab:!0,dropdownAlignRight:!1,windowPadding:0,virtualScroll:600,display:!1,sanitize:!0,sanitizeFn:null,whiteList:P},H.prototype={constructor:H,init:function(){var i=this,e=this.$element.attr("id"),t=this.$element[0],s=t.form;ee++,this.selectId="bs-select-"+ee,t.classList.add("bs-select-hidden"),this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),t.classList.contains("show-tick")&&(this.options.showTick=!0),this.$newElement=this.createDropdown(),this.$element.after(this.$newElement).prependTo(this.$newElement),s&&null===t.form&&(s.id||(s.id="form-"+this.selectId),t.setAttribute("form",s.id)),this.$button=this.$newElement.children("button"),this.options.allowClear&&(this.$clearButton=this.$button.children(".bs-select-clear-selected")),this.$menu=this.$newElement.children(z.MENU),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),t.classList.remove("bs-select-hidden"),this.fetchData(function(){i.render(!0),i.buildList(),requestAnimationFrame(function(){i.$element.trigger("loaded"+A)})}),!0===this.options.dropdownAlignRight&&this.$menu[0].classList.add(T.MENURIGHT),void 0!==e&&this.$button.attr("data-id",e),this.checkDisabled(),this.clickListener(),4'+this.options.header+""),this.options.liveSearch&&(o=''),this.multiple&&this.options.actionsBox&&(l='
"),this.multiple&&this.options.doneButton&&(r='
"),this.options.allowClear&&(a='×'),e='",$(e)},setPositionData:function(){this.selectpicker.view.canHighlight=[],this.selectpicker.view.size=0,this.selectpicker.view.firstHighlightIndex=!1;for(var e=0;e=this.options.virtualScroll||!0===this.options.virtualScroll},createView:function(y,e,t){var x=this,i=0;function E(e,t){var i,s=x.selectpicker.current.data.length,n=[],o=!0,l=x.isVirtual();x.selectpicker.view.scrollTop=e;for(var r,a=x.options.chunkSize,c=Math.ceil(s/a)||1,d=0;ds-1?0:x.selectpicker.current.data[s-1].position-x.selectpicker.current.data[x.selectpicker.view.position1-1].position,p.firstChild.style.marginTop=g+"px",p.firstChild.style.marginBottom=o+"px"):(p.firstChild.style.marginTop=0,p.firstChild.style.marginBottom=0),p.firstChild.appendChild(u),!0===l&&x.sizeInfo.hasScrollBar&&(f=p.firstChild.offsetWidth,t&&fx.sizeInfo.selectWidth?p.firstChild.style.minWidth=x.sizeInfo.menuInnerInnerWidth+"px":f>x.sizeInfo.menuInnerInnerWidth&&(x.$menu[0].style.minWidth=0,(g=p.firstChild.offsetWidth)>x.sizeInfo.menuInnerInnerWidth&&(x.sizeInfo.menuInnerInnerWidth=g,p.firstChild.style.minWidth=x.sizeInfo.menuInnerInnerWidth+"px"),x.$menu[0].style.minWidth=""))}(!y&&x.options.source.data||y&&x.options.source.search)&&x.selectpicker.current.hasMore&&i===c-1&&0 *:not(:disabled)"))?o.index:0,l=(l=window.performance&&window.performance.getEntriesByType("navigation"))&&l.length?"back_forward"!==l[0].type:2!==window.performance.navigation.type,i&&(this.selectpicker.view.titleOption.className="bs-title-option",this.selectpicker.view.titleOption.value="",t=!n||s===o&&!1===n.defaultSelected&&void 0===this.$element.data("selected")),!i&&0===this.selectpicker.view.titleOption.index||e.insertBefore(this.selectpicker.view.titleOption,e.firstChild),t&&l?e.selectedIndex=0:"complete"!==document.readyState&&window.addEventListener("pageshow",function(){r.selectpicker.view.displayedValue!==e.value&&r.render()})),a},fetchData:function(n,o,e,t){e=e||1,o=o||"data";var l,r=this,i=this.options.source[o];i?(this.options.virtualScroll=!0,"function"==typeof i?i.call(this,function(e,t,i){var s=r.selectpicker["search"===o?"search":"main"];s.hasMore=t,s.totalItems=i,l=r.buildData(e,o),n.call(r,l),r.$element.trigger("fetched"+A)},e,t):Array.isArray(i)&&(l=r.buildData(i,o),n.call(r,l))):(l=this.buildData(!1,o),n.call(r,l))},buildData:function(h,e){var o=this,p=!1===h?N.fromOption:N.fromDataSource,u=':not([hidden]):not([data-hidden="true"]):not([style*="display: none"])',f=[],l=this.selectpicker.main.data?this.selectpicker.main.data.length:0,m=0,v=this.setPlaceholder()&&!h?1:0,t=("search"===e&&(l=this.selectpicker.search.data.length),this.options.hideDisabled&&(u+=":not(:disabled)"),h?h.filter(ne,this):this.$element[0].querySelectorAll("select > *"+u));function g(e){var t=f[f.length-1];t&&"divider"===t.type&&(t.optID||e.optID)||((e=e||{}).type="divider",f.push(e))}function b(e,t){var i,s,n;(t=t||{}).divider=p(e,"divider"),!0===t.divider?g({optID:t.optID}):(i=f.length+l,s=(s=p(e,"style"))?k(s):"",n=(e.className||"")+(t.optgroupClass||""),t.optID&&(n="opt "+n),t.optionClass=n.trim(),t.inlineStyle=s,t.text=p(e,"text"),t.title=p(e,"title"),t.content=p(e,"content"),t.tokens=p(e,"tokens"),t.subtext=p(e,"subtext"),t.icon=p(e,"icon"),t.display=t.content||t.text,t.value=void 0===e.value?e.text:e.value,t.type="option",t.index=i,t.option=e.option||e,t.option.liIndex=i,t.selected=!!e.selected,t.disabled=t.disabled||!!e.disabled,!1!==h&&(o.selectpicker.optionValuesDataMap[t.value]?t=$.extend(o.selectpicker.optionValuesDataMap[t.value],t):o.selectpicker.optionValuesDataMap[t.value]=t),f.push(t))}function i(e,t){var i=t[e],s=!(e-1 li")},render:function(e){var i=this,t=this.$element[0],s=this.setPlaceholder()&&0===t.selectedIndex,n=y.call(this),o=n.length,l=x.call(this,n),r=this.$button[0],a=r.querySelector(".filter-option-inner-inner"),c=document.createTextNode(this.options.multipleSeparator),d=D.fragment.cloneNode(!1),h=!1;if(this.options.source.data&&e&&(n.map(function e(t){t.selected?i.createOption(t,!0):t.children&&t.children.length&&t.children.map(e)}),t.appendChild(this.selectpicker.main.optionQueue),s=s&&0===t.selectedIndex),r.classList.toggle("bs-placeholder",i.multiple?!o:!l&&0!==l),i.multiple||1!==n.length||(i.selectpicker.view.displayedValue=l),"static"===this.options.selectedTextFormat)d=L.text.call(this,{text:this.options.placeholder},!0);else if(!1===(this.multiple&&-1!==this.options.selectedTextFormat.indexOf("count")&&0")).length&&o>e[1]||1===e.length&&2<=o))){if(!s){for(var p=0;p option"+t+", optgroup"+t+" option"+t).length),e="function"==typeof this.options.countSelectedText?this.options.countSelectedText(o,l):this.options.countSelectedText,d=L.text.call(this,{text:e.replace("{0}",o.toString()).replace("{1}",l.toString())},!0);d.childNodes.length||(d=L.text.call(this,{text:this.options.placeholder||this.options.noneSelectedText},!0)),r.title=d.textContent.replace(/<[^>]*>?/g,"").trim(),this.options.sanitize&&h&&S([d],i.options.whiteList,i.options.sanitizeFn),a.innerHTML="",a.appendChild(d),g.major<4&&this.$newElement[0].classList.contains("bs3-has-addon")&&(s=r.querySelector(".filter-expand"),(t=a.cloneNode(!0)).className="filter-expand",s?r.replaceChild(t,s):r.appendChild(t)),this.$element.trigger("rendered"+A)},setStyle:function(e,t){var i=this.$button[0],s=this.$newElement[0],n=this.options.style.trim();this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,"")),g.major<4&&(s.classList.add("bs3"),s.parentNode.classList&&s.parentNode.classList.contains("input-group")&&(s.previousElementSibling||s.nextElementSibling)&&(s.previousElementSibling||s.nextElementSibling).classList.contains("input-group-addon")&&s.classList.add("bs3-has-addon")),s=e?e.trim():n,"add"==t?s&&i.classList.add.apply(i.classList,s.split(" ")):"remove"==t?s&&i.classList.remove.apply(i.classList,s.split(" ")):(n&&i.classList.remove.apply(i.classList,n.split(" ")),s&&i.classList.add.apply(i.classList,s.split(" ")))},liHeight:function(e){if(e||!1!==this.options.size&&!Object.keys(this.sizeInfo).length){var t,e=D.div.cloneNode(!1),i=D.div.cloneNode(!1),s=D.div.cloneNode(!1),n=document.createElement("ul"),o=D.li.cloneNode(!1),l=D.li.cloneNode(!1),r=D.a.cloneNode(!1),a=D.span.cloneNode(!1),c=this.options.header&&0this.sizeInfo.menuExtras.vert&&l+this.sizeInfo.menuExtras.vert+50>this.sizeInfo.selectOffsetBot,!0===this.selectpicker.isSearching&&(l=this.selectpicker.dropup),this.$newElement.toggleClass(T.DROPUP,l),this.selectpicker.dropup=l),"auto"===this.options.size)l=3this.options.size){for(var v=0;vthis.sizeInfo.menuInnerHeight&&(this.sizeInfo.hasScrollBar=!0,this.sizeInfo.totalMenuWidth=this.sizeInfo.menuWidth+this.sizeInfo.scrollBarWidth),"auto"===this.options.dropdownAlignRight&&this.$menu.toggleClass(T.MENURIGHT,this.sizeInfo.selectOffsetLeft>this.sizeInfo.selectOffsetRight&&this.sizeInfo.selectOffsetRightthis.options.size&&i.off("resize"+A+"."+this.selectId+".setMenuSize scroll"+A+"."+this.selectId+".setMenuSize")),this.createView(!1,!0,e)},setWidth:function(){var i=this;"auto"===this.options.width?requestAnimationFrame(function(){i.$menu.css("min-width","0"),i.$element.on("loaded"+A,function(){i.liHeight(),i.setMenuSize();var e=i.$newElement.clone().appendTo("body"),t=e.css("width","auto").children("button").outerWidth();e.remove(),i.sizeInfo.selectWidth=Math.max(i.sizeInfo.totalMenuWidth,t),i.$newElement.css("width",i.sizeInfo.selectWidth+"px")})}):"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width","")),this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement[0].classList.remove("fit-width")},selectPosition:function(){this.$bsContainer=$('
');function e(e){var t={},i=l.options.display||!!$.fn.dropdown.Constructor.Default&&$.fn.dropdown.Constructor.Default.display;l.$bsContainer.addClass(e.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass(T.DROPUP,e.hasClass(T.DROPUP)),s=e.offset(),r.is("body")?n={top:0,left:0}:((n=r.offset()).top+=parseInt(r.css("borderTopWidth"))-r.scrollTop(),n.left+=parseInt(r.css("borderLeftWidth"))-r.scrollLeft()),o=e.hasClass(T.DROPUP)?0:e[0].offsetHeight,(g.major<4||"static"===i)&&(t.top=s.top-n.top+o,t.left=s.left-n.left),t.width=e[0].offsetWidth,l.$bsContainer.css(t)}var s,n,o,l=this,r=$(this.options.container);this.$button.on("click.bs.dropdown.data-api",function(){l.isDisabled()||(e(l.$newElement),l.$bsContainer.appendTo(l.options.container).toggleClass(T.SHOW,!l.$button.hasClass(T.SHOW)).append(l.$menu))}),$(window).off("resize"+A+"."+this.selectId+" scroll"+A+"."+this.selectId).on("resize"+A+"."+this.selectId+" scroll"+A+"."+this.selectId,function(){l.$newElement.hasClass(T.SHOW)&&e(l.$newElement)}),this.$element.on("hide"+A,function(){l.$menu.data("height",l.$menu.height()),l.$bsContainer.detach()})},createOption:function(e,t){var i,s=e.option||e;s&&1!==s.nodeType&&(i=(t?D.selectedOption:D.option).cloneNode(!0),void 0!==s.value&&(i.value=s.value),i.textContent=s.text,i.selected=!0,void 0!==s.liIndex?i.liIndex=s.liIndex:t||(i.liIndex=e.index),e.option=i,this.selectpicker.main.optionQueue.appendChild(i))},setOptionStatus:function(e){var t=this;if(t.noScroll=!1,t.selectpicker.view.visibleElements&&t.selectpicker.view.visibleElements.length){for(var i=0;i
');d[2]&&(b=b.replace("{var}",d[2][1"+b+"")),c=!1,I.$element.trigger("maxReached"+A)),h&&t&&(k.append($("
"+w+"
")),c=!1,I.$element.trigger("maxReachedGrp"+A)),setTimeout(function(){I.setSelected(o,!1)},10),k[0].classList.add("fadeOut"),setTimeout(function(){k.remove()},1050)}}}else a&&I.setSelected(a,!1),I.setSelected(o,!0);I.options.source.data&&I.$element[0].appendChild(I.selectpicker.main.optionQueue),!I.multiple||I.multiple&&1===I.options.maxOptions?I.$button.trigger("focus"):I.options.liveSearch&&I.$searchbox.trigger("focus"),!c||!I.multiple&&r===s.selectedIndex||(E=[e.index,i.prop("selected"),l],I.$element.triggerNative("change"))}}),this.$menu.on("click","li."+T.DISABLED+" a, ."+T.POPOVERHEADER+", ."+T.POPOVERHEADER+" :not(.close)",function(e){e.currentTarget==this&&(e.preventDefault(),e.stopPropagation(),(I.options.liveSearch&&!$(e.target).hasClass("close")?I.$searchbox:I.$button).trigger("focus"))}),this.$menuInner.on("click",".divider, .dropdown-header",function(e){e.preventDefault(),e.stopPropagation(),(I.options.liveSearch?I.$searchbox:I.$button).trigger("focus")}),this.$menu.on("click","."+T.POPOVERHEADER+" .close",function(){I.$button.trigger("click")}),this.$searchbox.on("click",function(e){e.stopPropagation()}),this.$menu.on("click",".actions-btn",function(e){(I.options.liveSearch?I.$searchbox:I.$button).trigger("focus"),e.preventDefault(),e.stopPropagation(),$(this).hasClass("bs-select-all")?I.selectAll():I.deselectAll()}),this.$button.on("focus"+A,function(e){var t=I.$element[0].getAttribute("tabindex");void 0!==t&&e.originalEvent&&e.originalEvent.isTrusted&&(this.setAttribute("tabindex",t),I.$element[0].setAttribute("tabindex",-1),I.selectpicker.view.tabindex=t)}).on("blur"+A,function(e){void 0!==I.selectpicker.view.tabindex&&e.originalEvent&&e.originalEvent.isTrusted&&(I.$element[0].setAttribute("tabindex",I.selectpicker.view.tabindex),this.setAttribute("tabindex",-1),I.selectpicker.view.tabindex=void 0)}),this.$element.on("change"+A,function(){I.render(),I.$element.trigger("changed"+A,E),E=null}).on("focus"+A,function(){I.options.mobile||I.$button[0].focus()})},liveSearchListener:function(){var p=this;this.$button.on("click.bs.dropdown.data-api",function(){p.$searchbox.val()&&(p.$searchbox.val(""),p.selectpicker.search.previousValue=void 0)}),this.$searchbox.on("click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api",function(e){e.stopPropagation()}),this.$searchbox.on("input propertychange",function(){var t=p.$searchbox[0].value;if(p.selectpicker.search.elements=[],p.selectpicker.search.data=[],t)if(p.selectpicker.search.previousValue=t,p.options.source.search)p.fetchData(function(e){p.render(),p.buildList(void 0,!0),p.noScroll=!0,p.$menuInner.scrollTop(0),p.createView(!0),se.call(p,e,t)},"search",0,t);else{var e=[],i=t.toUpperCase(),s={},n=[],o=p._searchStyle(),l=p.options.liveSearchNormalize;l&&(i=u(i));for(var r=0;r=r.selectpicker.view.canHighlight.length&&(d=r.selectpicker.view.firstHighlightIndex),r.selectpicker.view.canHighlight[d+p]||(d=d+1+r.selectpicker.view.canHighlight.slice(d+p+1).indexOf(!0))),e.preventDefault();var u=p+d;e.which===C?0===p&&d===a.length-1?(r.$menuInner[0].scrollTop=r.$menuInner[0].scrollHeight,u=r.selectpicker.current.elements.length-1):(s=r.selectpicker.current.data[u])&&(c=(n=s.position-s.height)h+r.sizeInfo.menuInnerHeight),i=r.selectpicker.main.elements[l],r.activeElement=i,r.focusItem(i),i&&i.firstChild.focus(),c&&(r.$menuInner[0].scrollTop=n),o.trigger("focus"))}t&&(e.which===w&&!r.selectpicker.keydown.keyHistory||e.which===J||e.which===I&&r.options.selectOnTab)&&(e.which!==w&&e.preventDefault(),r.options.liveSearch&&e.which===w||(r.$menuInner.find(".active a").trigger("click",!0),o.trigger("focus"),r.options.liveSearch||(e.preventDefault(),$(document).data("spaceSelect",!0))))}},mobile:function(){this.options.mobile=!0,this.$element[0].classList.add("mobile-device")},refresh:function(){var e=this,t=$.extend({},this.options,d(this.$element),this.$element.data());this.options=t,this.options.source.data?(this.render(),this.buildList()):this.fetchData(function(){e.render(),e.buildList()}),this.checkDisabled(),this.setStyle(),this.setWidth(),this.setSize(!0),this.$element.trigger("refreshed"+A)},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),(this.$bsContainer||this.$menu).remove(),this.selectpicker.view.titleOption&&this.selectpicker.view.titleOption.parentNode&&this.selectpicker.view.titleOption.parentNode.removeChild(this.selectpicker.view.titleOption),this.$element.off(A).removeData("selectpicker").removeClass("bs-select-hidden selectpicker mobile-device"),$(window).off(A+"."+this.selectId)}};var le=$.fn.selectpicker;function re(){return g.major<5?$.fn.dropdown?($.fn.dropdown.Constructor._dataApiKeydownHandler||$.fn.dropdown.Constructor.prototype.keydown).apply(this,arguments):void 0:m.dataApiKeydownHandler}$.fn.selectpicker=oe,$.fn.selectpicker.Constructor=H,$.fn.selectpicker.noConflict=function(){return $.fn.selectpicker=le,this},$(document).off("keydown.bs.dropdown.data-api").on("keydown.bs.dropdown.data-api",":not(.bootstrap-select) > ["+z.DATA_TOGGLE+"]",re).on("keydown.bs.dropdown.data-api",":not(.bootstrap-select) > .dropdown-menu",re).on("keydown"+A,".bootstrap-select ["+z.DATA_TOGGLE+'], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input',H.prototype.keydown).on("focusin.modal",".bootstrap-select ["+z.DATA_TOGGLE+'], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input',function(e){e.stopPropagation()}),document.addEventListener("DOMContentLoaded",function(){$(".selectpicker").each(function(){var e=$(this);oe.call(e,e.data())})})}(e)}); diff --git a/src/MasterData.Web/wwwroot/js/bootstrap/bootstrap-tagsinput/bootstrap-tagsinput.min.js b/src/MasterData.Web/wwwroot/js/bootstrap/bootstrap-tagsinput/bootstrap-tagsinput.min.js deleted file mode 100644 index 6e43fbaee..000000000 --- a/src/MasterData.Web/wwwroot/js/bootstrap/bootstrap-tagsinput/bootstrap-tagsinput.min.js +++ /dev/null @@ -1 +0,0 @@ -!function (t) { "use strict"; var e = { tagClass: function (t) { return bootstrapVersion == 3 ? "label label-info" : "badge text-bg-primary" }, itemValue: function (t) { return t ? t.toString() : t }, itemText: function (t) { return this.itemValue(t) }, itemTitle: function (t) { return null }, freeInput: !0, addOnBlur: !0, maxTags: void 0, maxChars: void 0, confirmKeys: [13, 44], delimiter: ",", delimiterRegex: null, cancelConfirmKeysOnEmpty: !0, onTagExists: function (t, e) { e.hide().fadeIn() }, trimValue: !1, allowDuplicates: !1 }; function i(e, i) { this.itemsArray = [], this.$element = t(e), this.$element.hide(), this.isSelect = "SELECT" === e.tagName, this.multiple = this.isSelect && e.hasAttribute("multiple"), this.objectItems = i && i.itemValue, this.placeholderText = e.hasAttribute("placeholder") ? this.$element.attr("placeholder") : "", this.inputSize = Math.max(40, this.placeholderText.length), this.$container = t('
'), this.$input = t('').appendTo(this.$container), this.$element.before(this.$container), this.build(i) } function n(t, e) { if ("function" != typeof t[e]) { var i = t[e]; t[e] = function (t) { return t[i] } } } function a(t, e) { if ("function" != typeof t[e]) { var i = t[e]; t[e] = function () { return i } } } i.prototype = { constructor: i, add: function (e, i, n) { var a = this; if (!(a.options.maxTags && a.itemsArray.length >= a.options.maxTags) && (!1 === e || e)) { if ("string" == typeof e && a.options.trimValue && (e = t.trim(e)), "object" == typeof e && !a.objectItems) throw "Can't add objects when itemValue option is not set"; if (!e.toString().match(/^\s*$/)) { if (a.isSelect && !a.multiple && a.itemsArray.length > 0 && a.remove(a.itemsArray[0]), "string" == typeof e && "INPUT" === this.$element[0].tagName) { var o = a.options.delimiterRegex ? a.options.delimiterRegex : a.options.delimiter, s = e.split(o); if (s.length > 1) { for (var l = 0; l < s.length; l++)this.add(s[l], !0); return void (i || a.pushVal()) } } var u = a.options.itemValue(e), p = a.options.itemText(e), c = a.options.tagClass(e), h = a.options.itemTitle(e), m = t.grep(a.itemsArray, function (t) { return a.options.itemValue(t) === u })[0]; if (!m || a.options.allowDuplicates) { if (!(a.items().toString().length + e.length + 1 > a.options.maxInputLength)) { var f = t.Event("beforeItemAdd", { item: e, cancel: !1, options: n }); if (a.$element.trigger(f), !f.cancel) { a.itemsArray.push(e); var d = t('' + r(p) + ''); if (d.data("item", e), a.findInputWrapper().before(d), d.after(" "), a.isSelect && !t('option[value="' + encodeURIComponent(u) + '"]', a.$element)[0]) { var g = t(""); g.data("item", e), g.attr("value", u), a.$element.append(g) } i || a.pushVal(), a.options.maxTags !== a.itemsArray.length && a.items().toString().length !== a.options.maxInputLength || a.$container.addClass("bootstrap-tagsinput-max"), a.$element.trigger(t.Event("itemAdded", { item: e, options: n })) } } } else if (a.options.onTagExists) { var v = t(".tag", a.$container).filter(function () { return t(this).data("item") === m }); a.options.onTagExists(e, v) } } } }, remove: function (e, i, n) { var a = this; if (a.objectItems && (e = (e = "object" == typeof e ? t.grep(a.itemsArray, function (t) { return a.options.itemValue(t) == a.options.itemValue(e) }) : t.grep(a.itemsArray, function (t) { return a.options.itemValue(t) == e }))[e.length - 1]), e) { var o = t.Event("beforeItemRemove", { item: e, cancel: !1, options: n }); if (a.$element.trigger(o), o.cancel) return; t(".tag", a.$container).filter(function () { return t(this).data("item") === e }).remove(), t("option", a.$element).filter(function () { return t(this).data("item") === e }).remove(), -1 !== t.inArray(e, a.itemsArray) && a.itemsArray.splice(t.inArray(e, a.itemsArray), 1) } i || a.pushVal(), a.options.maxTags > a.itemsArray.length && a.$container.removeClass("bootstrap-tagsinput-max"), a.$element.trigger(t.Event("itemRemoved", { item: e, options: n })) }, removeAll: function () { for (t(".tag", this.$container).remove(), t("option", this.$element).remove(); this.itemsArray.length > 0;)this.itemsArray.pop(); this.pushVal() }, refresh: function () { var e = this; t(".tag", e.$container).each(function () { var i = t(this), n = i.data("item"), a = e.options.itemValue(n), o = e.options.itemText(n), s = e.options.tagClass(n); (i.attr("class", null), i.addClass("tag " + r(s)), i.contents().filter(function () { return 3 == this.nodeType })[0].nodeValue = r(o), e.isSelect) && t("option", e.$element).filter(function () { return t(this).data("item") === n }).attr("value", a) }) }, items: function () { return this.itemsArray }, pushVal: function () { var e = this, i = t.map(e.items(), function (t) { return e.options.itemValue(t).toString() }); e.$element.val(i, !0).trigger("change") }, build: function (i) { var o = this; if (o.options = t.extend({}, e, i), o.objectItems && (o.options.freeInput = !1), n(o.options, "itemValue"), n(o.options, "itemText"), a(o.options, "tagClass"), o.options.typeahead) { var r = o.options.typeahead || {}; a(r, "source"), o.$input.typeahead(t.extend({}, r, { source: function (e, i) { function n(t) { for (var e = [], n = 0; n < t.length; n++) { var r = o.options.itemText(t[n]); a[r] = t[n], e.push(r) } i(e) } this.map = {}; var a = this.map, s = r.source(e); t.isFunction(s.success) ? s.success(n) : t.isFunction(s.then) ? s.then(n) : t.when(s).then(n) }, updater: function (t) { return o.add(this.map[t]), this.map[t] }, matcher: function (t) { return -1 !== t.toLowerCase().indexOf(this.query.trim().toLowerCase()) }, sorter: function (t) { return t.sort() }, highlighter: function (t) { var e = new RegExp("(" + this.query + ")", "gi"); return t.replace(e, "$1") } })) } if (o.options.typeaheadjs) { var l = null, u = {}, p = o.options.typeaheadjs; t.isArray(p) ? (l = p[0], u = p[1]) : u = p, o.$input.typeahead(l, u).on("typeahead:selected", t.proxy(function (t, e) { u.valueKey ? o.add(e[u.valueKey]) : o.add(e), o.$input.typeahead("val", "") }, o)) } o.$container.on("click", t.proxy(function (t) { o.$element.attr("disabled") || o.$input.removeAttr("disabled"), o.$input.focus() }, o)), o.options.addOnBlur && o.options.freeInput && o.$input.on("focusout", t.proxy(function (e) { 0 === t(".typeahead, .twitter-typeahead", o.$container).length && (o.add(o.$input.val()), o.$input.val("")) }, o)), o.$container.on("keydown", "input", t.proxy(function (e) { var i = t(e.target), n = o.findInputWrapper(); if (o.$element.attr("disabled")) o.$input.attr("disabled", "disabled"); else { switch (e.which) { case 8: if (0 === s(i[0])) { var a = n.prev(); a.length && o.remove(a.data("item")) } break; case 46: if (0 === s(i[0])) { var r = n.next(); r.length && o.remove(r.data("item")) } break; case 37: var l = n.prev(); 0 === i.val().length && l[0] && (l.before(n), i.focus()); break; case 39: var u = n.next(); 0 === i.val().length && u[0] && (u.after(n), i.focus()) }var p = i.val().length; Math.ceil(p / 5); i.attr("size", Math.max(this.inputSize, i.val().length)) } }, o)), o.$container.on("keypress", "input", t.proxy(function (e) { var i = t(e.target); if (o.$element.attr("disabled")) o.$input.attr("disabled", "disabled"); else { var n, a, r, s = i.val(), l = o.options.maxChars && s.length >= o.options.maxChars; o.options.freeInput && (n = e, a = o.options.confirmKeys, r = !1, t.each(a, function (t, e) { if ("number" == typeof e && n.which === e) return r = !0, !1; if (n.which === e.which) { var i = !e.hasOwnProperty("altKey") || n.altKey === e.altKey, a = !e.hasOwnProperty("shiftKey") || n.shiftKey === e.shiftKey, o = !e.hasOwnProperty("ctrlKey") || n.ctrlKey === e.ctrlKey; if (i && a && o) return r = !0, !1 } }), r || l) && (0 !== s.length && (o.add(l ? s.substr(0, o.options.maxChars) : s), i.val("")), !1 === o.options.cancelConfirmKeysOnEmpty && e.preventDefault()); var u = i.val().length; Math.ceil(u / 5); i.attr("size", Math.max(this.inputSize, i.val().length)) } }, o)), o.$container.on("click", "[data-role=remove]", t.proxy(function (e) { o.$element.attr("disabled") || o.remove(t(e.target).closest(".tag").data("item")) }, o)), o.options.itemValue === e.itemValue && ("INPUT" === o.$element[0].tagName ? o.add(o.$element.val()) : t("option", o.$element).each(function () { o.add(t(this).attr("value"), !0) })) }, destroy: function () { this.$container.off("keypress", "input"), this.$container.off("click", "[role=remove]"), this.$container.remove(), this.$element.removeData("tagsinput"), this.$element.show() }, focus: function () { this.$input.focus() }, input: function () { return this.$input }, findInputWrapper: function () { for (var e = this.$input[0], i = this.$container[0]; e && e.parentNode !== i;)e = e.parentNode; return t(e) } }, t.fn.tagsinput = function (e, n, a) { var o = []; return this.each(function () { var r = t(this).data("tagsinput"); if (r) if (e || n) { if (void 0 !== r[e]) { if (3 === r[e].length && void 0 !== a) var s = r[e](n, null, a); else s = r[e](n); void 0 !== s && o.push(s) } } else o.push(r); else r = new i(this, e), t(this).data("tagsinput", r), o.push(r), "SELECT" === this.tagName && t("option", t(this)).attr("selected", "selected"), t(this).val(t(this).val()) }), "string" == typeof e ? o.length > 1 ? o : o[0] : o }, t.fn.tagsinput.Constructor = i; var o = t("
"); function r(t) { return t ? o.text(t).html() : "" } function s(t) { var e = 0; if (document.selection) { t.focus(); var i = document.selection.createRange(); i.moveStart("character", -t.value.length), e = i.text.length } else (t.selectionStart || "0" == t.selectionStart) && (e = t.selectionStart); return e } t(function () { t("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput() }) }(window.jQuery); \ No newline at end of file diff --git a/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js b/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js index c11e06381..73b8c4f07 100644 --- a/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js +++ b/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js @@ -408,6 +408,9 @@ class CodeEditor { catch (_a) { return; } + if (!hints || typeof hints !== "object") { + return; + } Object.keys(hints).forEach(lang => { monaco.languages.registerCompletionItemProvider(lang, { provideCompletionItems: function (model, position) { @@ -1175,8 +1178,9 @@ class GridViewFilterHelper { if (currentObj.hasClass("flatpickr-input")) { currentObj.val(""); } - if (currentObj.hasClass("selectpicker")) { - currentObj.selectpicker("val", ""); + if (currentObj.hasClass("tom-select")) { + TomSelectHelper.clear(this); + return; } if (currentObj.typeahead) { currentObj.typeahead("val", ""); @@ -1190,15 +1194,9 @@ class GridViewFilterHelper { if (inputType == "checkbox") { currentObj.prop("checked", false); } - else if (inputType != "input" && currentObj.attr("data-role") == "tagsinput") { - currentObj.tagsinput('removeAll'); - } else if (inputType != "hidden") { currentObj.val(null); - if (currentObj.hasClass("selectpicker")) { - currentObj.selectpicker("render"); - } - else if (currentObj.hasClass("jj-search-box")) { + if (currentObj.hasClass("jj-search-box")) { currentObj[0].bootstrapSearch.clear(); } else if (currentObj.hasClass("jjlookup")) { @@ -1229,6 +1227,7 @@ class GridViewFilterHelper { success: (content) => { HTMLHelper.setOuterHTML(filterPanelName, content); listenAllEvents("#" + filterPanelName); + document.querySelector("#grid-view-filter-action-" + componentName).value = "clear"; GridViewHelper.refreshGrid(componentName, routeContext); document.getElementById(componentName + "-filter-icon").classList.add("d-none"); } @@ -1243,7 +1242,7 @@ class GridViewFilterHelper { static searchOnDOM(componentName, oDom) { const value = $(oDom).val().toString().toLowerCase(); $("#" + componentName + "-table" + " tr").filter(function () { - const textValues = $(this).clone().find('.bootstrap-select, .selectpicker, select').remove().end().text(); + const textValues = $(this).clone().find('.ts-wrapper, .tom-select, select').remove().end().text(); let isSearch = textValues.toLowerCase().indexOf(value) > -1; if (!isSearch) { var valueNew = value.replace(",", "").replace(".", "").replace("-", ""); @@ -1733,10 +1732,7 @@ class LegacySearchBoxListener { const listenAllEvents = (selectorPrefix = String()) => { var _a; selectorPrefix += " "; - $(selectorPrefix + ".selectpicker").selectpicker({ - iconBase: bootstrapVersion === 5 ? 'fa' : 'glyphicon', - styleBase: bootstrapVersion === 5 ? "form-select form-dropdown" : "form-control" - }); + TomSelectHelper.listen(selectorPrefix); if (bootstrapVersion === 3) { $(selectorPrefix + "input[type=checkbox][data-toggle^=toggle]").bootstrapToggle(); } @@ -2468,7 +2464,7 @@ class PhoneInputListener { }).mask(input); } function syncHiddenInput(input, select) { - const hiddenInput = $(input).closest('.input-group').find('.jj-phone-hidden-input')[0]; + const hiddenInput = $(input).closest('.jj-phone-group').find('.jj-phone-hidden-input')[0]; if (!hiddenInput) return; const selectedOption = select.selectedOptions[0]; @@ -2478,14 +2474,12 @@ class PhoneInputListener { } const selects = document.querySelectorAll(`${selectorPrefix}select.jj-phone-select`); selects.forEach(select => { - $(select).on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) { - if (isSelected) { - const input = $(select).closest('.input-group').find('.jj-phone-input')[0]; - if (!input) - return; - applyMask(input); - syncHiddenInput(input, select); - } + select.addEventListener('change', () => { + const input = $(select).closest('.input-group').find('.jj-phone-input')[0]; + if (!input) + return; + applyMask(input); + syncHiddenInput(input, select); }); }); const inputs = document.querySelectorAll(`${selectorPrefix}input.jj-phone-input`); @@ -2493,7 +2487,7 @@ class PhoneInputListener { const select = $(input).closest('.input-group').find('select.jj-phone-select')[0]; if (!select) return; - const hiddenInput = $(input).closest('.input-group').find('.jj-phone-hidden-input')[0]; + const hiddenInput = $(input).closest('.jj-phone-group').find('.jj-phone-hidden-input')[0]; const options = [...select.options]; const longestDialCode = options.reduce((longest, current) => { const dialCode = normalizeDialCode(current.getAttribute('dial-code')); @@ -2515,7 +2509,7 @@ class PhoneInputListener { if (hiddenInput === null || hiddenInput === void 0 ? void 0 : hiddenInput.value.startsWith('+')) { const optionCountrySelected = getCountryFromInputValue(hiddenInput.value); if (optionCountrySelected) - $(select).selectpicker('val', optionCountrySelected.value); + TomSelectHelper.setValue(select, optionCountrySelected.value); } const selectedOption = select.selectedOptions[0] || options.find(option => option.value === $(select).val()); if (selectedOption) { @@ -2857,10 +2851,11 @@ class TextAreaListener { } } class TextFileHelper { - static showUploadView(fieldName, title, routeContext) { + static showUploadView(fieldName, title, routeContext, draftInputId) { const urlBuilder = new UrlBuilder(); urlBuilder.addQueryParameter("routeContext", routeContext); urlBuilder.addQueryParameter("fieldName", fieldName); + this.addDraftId(urlBuilder, draftInputId); const url = urlBuilder.build(); const modalId = fieldName + "-upload-modal"; const modal = new Modal(); @@ -2875,10 +2870,11 @@ class TextFileHelper { listenAllEvents("#" + modalId); }); } - static refresh(fieldName, routeContext) { + static refresh(fieldName, routeContext, draftInputId) { const urlBuilder = new UrlBuilder(); urlBuilder.addQueryParameter("routeContext", routeContext); urlBuilder.addQueryParameter("fieldName", fieldName); + this.addDraftId(urlBuilder, draftInputId); const url = urlBuilder.build(); postFormValues({ url: url, success: function (html) { const uploadViewSelector = "#" + fieldName + "-upload-view"; @@ -2897,6 +2893,69 @@ class TextFileHelper { valueElement.value = valueText; } } + static addDraftId(urlBuilder, draftInputId) { + const draftInput = document.getElementById(draftInputId); + if (draftInput === null || draftInput === void 0 ? void 0 : draftInput.value) { + urlBuilder.addQueryParameter("draftId", draftInput.value); + } + } +} +class TomSelectHelper { + static listen(selectorPrefix = String()) { + document.querySelectorAll(`${selectorPrefix} select.tom-select, ${selectorPrefix} input.tom-select`) + .forEach(element => this.initialize(element)); + } + static initialize(element) { + var _a, _b, _c, _d, _e; + if (element.tomselect) + return element.tomselect; + const isTagsInput = element instanceof HTMLInputElement && element.dataset.tomSelectTags === 'true'; + const isMultiSelect = element instanceof HTMLSelectElement && element.multiple; + if (isTagsInput) + element.value = element.value + .split(',') + .map(value => value.trim()) + .filter(Boolean) + .join(','); + const placeholder = (_e = (_b = (_a = element.dataset.placeholder) !== null && _a !== void 0 ? _a : element.getAttribute('placeholder')) !== null && _b !== void 0 ? _b : (element instanceof HTMLSelectElement + ? (_d = (_c = element.querySelector('option[value=""]')) === null || _c === void 0 ? void 0 : _c.textContent) === null || _d === void 0 ? void 0 : _d.trim() + : undefined)) !== null && _e !== void 0 ? _e : String(); + return new TomSelect(element, Object.assign(Object.assign({ allowEmptyOption: !isTagsInput, hidePlaceholder: false, hideSelected: false, maxOptions: null, placeholder }, (isTagsInput + ? { + create: true, + delimiter: ',' + } + : { + create: false, + controlInput: null, + plugins: isMultiSelect ? ['checkbox_options'] : [] + })), { render: { + no_results: () => { var _a; return `
${(_a = element.dataset.noResultsText) !== null && _a !== void 0 ? _a : 'No results found.'}
`; }, + option: (data, escape) => this.renderOption(element, data, escape, true), + item: (data, escape) => this.renderOption(element, data, escape, false) + } })); + } + static destroy(element) { + var _a; + (_a = element.tomselect) === null || _a === void 0 ? void 0 : _a.destroy(); + } + static setValue(element, value) { + const tomSelect = this.initialize(element); + tomSelect.setValue(value); + } + static clear(element) { + const tomSelect = this.initialize(element); + tomSelect.clear(); + } + static renderOption(element, data, escape, isDropdownItem) { + const option = element instanceof HTMLSelectElement + ? [...element.options].find(item => item.value === data.value) + : undefined; + const content = option === null || option === void 0 ? void 0 : option.dataset.content; + const cssClass = isDropdownItem ? 'ts-option-content' : String(); + const itemContent = content !== null && content !== void 0 ? content : escape(data.text); + return `
${itemContent}
`; + } } class TooltipHelper { static dispose(selectorPrefix) { @@ -3022,12 +3081,14 @@ class UploadAreaOptions { let queryStringParams = element.getAttribute("query-string-params"); const urlBuilder = new UrlBuilder(); urlBuilder.addQueryParameter("routeContext", routeContext); - const params = queryStringParams.split('&'); + const params = queryStringParams ? queryStringParams.split('&') : []; for (let i = 0; i < params.length; i++) { const param = params[i].split('='); const key = decodeURIComponent(param[0]); const value = decodeURIComponent(param[1]); - urlBuilder.addQueryParameter(key, value); + if (key) { + urlBuilder.addQueryParameter(key, value); + } } this.url = urlBuilder.build(); } @@ -3061,13 +3122,43 @@ class UploadViewHelper { eval(jsCallback); this.clearFileAction(componentName, fileName); } + static markDeleted(componentName, fileName, confirmationMessage, jsCallback, deletedInputId) { + if (confirmationMessage) { + const confirmed = confirm(confirmationMessage); + if (!confirmed) { + return; + } + } + const deletedInput = document.getElementById(deletedInputId); + if (!deletedInput) { + return; + } + const deletedFiles = deletedInput.value + .split(",") + .map(value => value.trim()) + .filter(value => value.length > 0); + if (deletedFiles.indexOf(fileName) === -1) { + deletedFiles.push(fileName); + deletedInput.value = deletedFiles.join(","); + } + eval(jsCallback); + } static downloadFile(componentName, fileName, jsCallback) { this.performFileAction(componentName, fileName, "downloadFile"); eval(jsCallback); this.clearFileAction(componentName, fileName); } static renameFile(componentName, fileName, promptMessage, jsCallback) { - this.performFileAction(componentName, fileName, "renameFile", promptMessage); + const newName = prompt(promptMessage, fileName); + if (newName === null || newName === fileName) { + return; + } + const uploadActionInput = document.getElementById("upload-view-action-" + componentName); + const filenameInput = document.getElementById("upload-view-file-name-" + componentName); + if (uploadActionInput && filenameInput) { + uploadActionInput.value = "renameFile"; + filenameInput.value = fileName + ";" + newName; + } eval(jsCallback); this.clearFileAction(componentName, fileName); } diff --git a/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js.map b/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js.map index 681d40d26..af8b38b79 100644 --- a/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js.map +++ b/src/MasterData.Web/wwwroot/js/jjmasterdata/jjmasterdata.js.map @@ -1 +1 @@ -{"version":3,"file":"jjmasterdata.js","sourceRoot":"/Scripts/","sources":["ActionHelper.ts","AuditLogViewHelper.ts","CalendarListener.ts","CheckboxHelper.ts","CodeEditor.ts","CollapsePanelListener.ts","DataDictionaryUtils.ts","DataExportationHelper.ts","DataImportationHelper.ts","DataImportationModal.ts","DataPanelHelper.ts","DecimalPlaces.ts","FeedbackIcon.ts","FormViewHelper.ts","GlobalVariables.ts","GridViewFilterHelper.ts","GridViewHelper.ts","GridViewSelectionHelper.ts","HTMLHelper.ts","Index.ts","JQueryPlugins.ts","LegacySearchBoxListener.ts","ListenAllEvents.ts","Localization.ts","LookupHelper.ts","LookupListener.ts","MasterDataForm.ts","MessageBox.ts","MessageToast.ts","Modal.ts","OffcanvasHelper.ts","PageState.ts","PhoneInputListener.ts","PopoverHelper.ts","PostFormValues.ts","SearchBoxListener.ts","SliderListener.ts","SortableListener.ts","SpinnerOverlay.ts","TabNavListener.ts","TextAreaListener.ts","TextFileHelper.ts","TooltipHelper.ts","UploadAreaListener.ts","UploadAreaOptions.ts","UploadViewHelper.ts","UrlBuilder.ts","UrlRedirectModel.ts","Utils.ts","WindowPlugins.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"jjmasterdata.js","sourceRoot":"/Scripts/","sources":["ActionHelper.ts","AuditLogViewHelper.ts","CalendarListener.ts","CheckboxHelper.ts","CodeEditor.ts","CollapsePanelListener.ts","DataDictionaryUtils.ts","DataExportationHelper.ts","DataImportationHelper.ts","DataImportationModal.ts","DataPanelHelper.ts","DecimalPlaces.ts","FeedbackIcon.ts","FormViewHelper.ts","GlobalVariables.ts","GridViewFilterHelper.ts","GridViewHelper.ts","GridViewSelectionHelper.ts","HTMLHelper.ts","Index.ts","LegacySearchBoxListener.ts","ListenAllEvents.ts","Localization.ts","LookupHelper.ts","LookupListener.ts","MasterDataForm.ts","MessageBox.ts","MessageToast.ts","Modal.ts","OffcanvasHelper.ts","PageState.ts","PhoneInputListener.ts","PopoverHelper.ts","PostFormValues.ts","SearchBoxListener.ts","SliderListener.ts","SortableListener.ts","SpinnerOverlay.ts","TabNavListener.ts","TextAreaListener.ts","TextFileHelper.ts","TomSelectHelper.ts","TooltipHelper.ts","UploadAreaListener.ts","UploadAreaOptions.ts","UploadViewHelper.ts","UrlBuilder.ts","UrlRedirectModel.ts","Utils.ts","WindowPlugins.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/MasterData.Web/wwwroot/js/tom-select/tom-select.complete.min.js b/src/MasterData.Web/wwwroot/js/tom-select/tom-select.complete.min.js new file mode 100644 index 000000000..10a0c4557 --- /dev/null +++ b/src/MasterData.Web/wwwroot/js/tom-select/tom-select.complete.min.js @@ -0,0 +1,454 @@ +/** +* Tom Select v2.6.2 +* Licensed under the Apache License, Version 2.0 (the "License"); +*/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TomSelect=t()}(this,function(){"use strict" +function e(e,t){e.split(/\s+/).forEach(e=>{t(e)})}class t{constructor(){this._events={}}on(t,i){e(t,e=>{const t=this._events[e]||[] +t.push(i),this._events[e]=t})}off(t,i){var s=arguments.length +0!==s?e(t,e=>{if(1===s)return void delete this._events[e] +const t=this._events[e] +void 0!==t&&(t.splice(t.indexOf(i),1),this._events[e]=t)}):this._events={}}trigger(t,...i){var s=this +e(t,e=>{const t=s._events[e] +void 0!==t&&t.forEach(e=>{e.apply(s,i)})})}}const i=e=>(e=e.filter(Boolean)).length<2?e[0]||"":1==l(e)?"["+e.join("")+"]":"(?:"+e.join("|")+")",s=e=>{if(!o(e))return e.join("") +let t="",i=0 +const s=()=>{i>1&&(t+="{"+i+"}")} +return e.forEach((n,o)=>{n!==e[o-1]?(s(),t+=n,i=1):i++}),s(),t},n=e=>{let t=Array.from(e) +return i(t)},o=e=>new Set(e).size!==e.length,r=e=>(e+"").replace(/([\$\(\)\*\+\.\?\[\]\^\{\|\}\\])/gu,"\\$1"),l=e=>e.reduce((e,t)=>Math.max(e,a(t)),0),a=e=>Array.from(e).length,c=e=>{if(1===e.length)return[[e]] +let t=[] +const i=e.substring(1) +return c(i).forEach(function(i){let s=i.slice(0) +s[0]=e.charAt(0)+s[0],t.push(s),s=i.slice(0),s.unshift(e.charAt(0)),t.push(s)}),t},d=[[0,65535]] +let u,p +const h={},g={"/":"⁄∕",0:"߀",a:"ⱥɐɑ",aa:"ꜳ",ae:"æǽǣ",ao:"ꜵ",au:"ꜷ",av:"ꜹꜻ",ay:"ꜽ",b:"ƀɓƃ",c:"ꜿƈȼↄ",d:"đɗɖᴅƌꮷԁɦ",e:"ɛǝᴇɇ",f:"ꝼƒ",g:"ǥɠꞡᵹꝿɢ",h:"ħⱨⱶɥ",i:"ɨı",j:"ɉȷ",k:"ƙⱪꝁꝃꝅꞣ",l:"łƚɫⱡꝉꝇꞁɭ",m:"ɱɯϻ",n:"ꞥƞɲꞑᴎлԉ",o:"øǿɔɵꝋꝍᴑ",oe:"œ",oi:"ƣ",oo:"ꝏ",ou:"ȣ",p:"ƥᵽꝑꝓꝕρ",q:"ꝗꝙɋ",r:"ɍɽꝛꞧꞃ",s:"ßȿꞩꞅʂ",t:"ŧƭʈⱦꞇ",th:"þ",tz:"ꜩ",u:"ʉ",v:"ʋꝟʌ",vy:"ꝡ",w:"ⱳ",y:"ƴɏỿ",z:"ƶȥɀⱬꝣ",hv:"ƕ"} +for(let e in g){let t=g[e]||"" +for(let i=0;ie.normalize(t),v=e=>Array.from(e).reduce((e,t)=>e+O(t),""),O=e=>(e=m(e).toLowerCase().replace(f,e=>h[e]||""),m(e,"NFC")) +const b=e=>{const t={},i=(e,i)=>{const s=t[e]||new Set,o=new RegExp("^"+n(s)+"$","iu") +i.match(o)||(s.add(r(i)),t[e]=s)} +for(let t of function*(e){for(const[t,i]of e)for(let e=t;e<=i;e++){let t=String.fromCharCode(e),i=v(t) +i!=t.toLowerCase()&&(i.length>3||0!=i.length&&(yield{folded:i,composed:t,code_point:e}))}}(e))i(t.folded,t.folded),i(t.folded,t.composed) +return t},y=e=>{const t=b(e),s={} +let o=[] +for(let e in t){let i=t[e] +i&&(s[e]=n(i)),e.length>1&&o.push(r(e))}o.sort((e,t)=>t.length-e.length) +const l=i(o) +return p=new RegExp("^"+l,"u"),s},w=(e,t=1)=>(t=Math.max(t,e.length-1),i(c(e).map(e=>((e,t=1)=>{let i=0 +return e=e.map(e=>(u[e]&&(i+=e.length),u[e]||e)),i>=t?s(e):""})(e,t)))),S=(e,t=!0)=>{let n=e.length>1?1:0 +return i(e.map(e=>{let i=[] +const o=t?e.length():e.length()-1 +for(let t=0;t{for(const i of t){if(i.start!=e.start||i.end!=e.end)continue +if(i.substrs.join("")!==e.substrs.join(""))continue +let t=e.parts +const s=e=>{for(const i of t){if(i.start===e.start&&i.substr===e.substr)return!1 +if(1!=e.length&&1!=i.length){if(e.starti.start)return!0 +if(i.starte.start)return!0}}return!1} +if(!(i.parts.filter(s).length>0))return!0}return!1} +class C{parts +substrs +start +end +constructor(){this.parts=[],this.substrs=[],this.start=0,this.end=0}add(e){e&&(this.parts.push(e),this.substrs.push(e.substr),this.start=Math.min(e.start,this.start),this.end=Math.max(e.end,this.end))}last(){return this.parts[this.parts.length-1]}length(){return this.parts.length}clone(e,t){let i=new C,s=JSON.parse(JSON.stringify(this.parts)),n=s.pop() +for(const e of s)i.add(e) +let o=t.substr.substring(0,e-n.start),r=o.length +return i.add({start:n.start,end:n.start+r,length:r,substr:o}),i}}const x=e=>{void 0===u&&(u=y(d)),e=v(e) +let t="",i=[new C] +for(let s=0;s0){l=l.sort((e,t)=>e.length()-t.length()) +for(let e of l)_(e,i)||i.push(e)}else if(s>0&&1==a.size&&!a.has("3")){t+=S(i,!1) +let e=new C +const s=i[0] +s&&e.add(s.last()),i=[e]}}return t+=S(i,!0),t},A=(e,t)=>{if(e)return e[t]},I=(e,t)=>{if(e){for(var i,s=t.split(".");(i=s.shift())&&(e=e[i]););return e}},k=(e,t,i)=>{var s,n +return e?(e+="",null==t.regex||-1===(n=e.search(t.regex))?0:(s=t.string.length/e.length,0===n&&(s+=.5),s*i)):0},F=(e,t)=>{var i=e[t] +if("function"==typeof i)return i +i&&!Array.isArray(i)&&(e[t]=[i])},L=(e,t)=>{if(Array.isArray(e))e.forEach(t) +else for(var i in e)e.hasOwnProperty(i)&&t(e[i],i)},E=(e,t)=>"number"==typeof e&&"number"==typeof t?e>t?1:e(t=v(t+"").toLowerCase())?1:t>e?-1:0 +class T{items +settings +constructor(e,t){this.items=e,this.settings=t||{diacritics:!0}}tokenize(e,t,i){if(!e||!e.length)return[] +const s=[],n=e.split(/\s+/) +var o +return i&&(o=new RegExp("^("+Object.keys(i).map(r).join("|")+"):(.*)$")),n.forEach(e=>{let i,n=null,l=null +o&&(i=e.match(o))&&(n=i[1],e=i[2]),e.length>0&&(l=this.settings.diacritics?x(e)||null:r(e),l&&t&&(l="\\b"+l)),s.push({string:e,regex:l?new RegExp(l,"iu"):null,field:n})}),s}getScoreFunction(e,t){var i=this.prepareSearch(e,t) +return this._getScoreFunction(i)}_getScoreFunction(e){const t=e.tokens,i=t.length +if(!i)return function(){return 0} +const s=e.options.fields,n=e.weights,o=s.length,r=e.getAttrFn +if(!o)return function(){return 1} +const l=1===o?function(e,t){const i=s[0].field +return k(r(t,i),e,n[i]||1)}:function(e,t){var i=0 +if(e.field){const s=r(t,e.field) +!e.regex&&s?i+=1/o:i+=k(s,e,1)}else L(n,(s,n)=>{i+=k(r(t,n),e,s)}) +return i/o} +return 1===i?function(e){return l(t[0],e)}:"and"===e.options.conjunction?function(e){var s,n=0 +for(let i of t){if((s=l(i,e))<=0)return 0 +n+=s}return n/i}:function(e){var s=0 +return L(t,t=>{s+=l(t,e)}),s/i}}getSortFunction(e,t){var i=this.prepareSearch(e,t) +return this._getSortFunction(i)}_getSortFunction(e){var t,i=[] +const s=this,n=e.options,o=!e.query&&n.sort_empty?n.sort_empty:n.sort +if("function"==typeof o)return o.bind(this) +const r=function(t,i){return"$score"===t?i.score:e.getAttrFn(s.items[i.id],t)} +if(o)for(let t of o)(e.query||"$score"!==t.field)&&i.push(t) +if(e.query){t=!0 +for(let e of i)if("$score"===e.field){t=!1 +break}t&&i.unshift({field:"$score",direction:"desc"})}else i=i.filter(e=>"$score"!==e.field) +return i.length?function(e,t){var s,n +for(let o of i){if(n=o.field,s=("desc"===o.direction?-1:1)*E(r(n,e),r(n,t)))return s}return 0}:null}prepareSearch(e,t){const i={} +var s=Object.assign({},t) +if(F(s,"sort"),F(s,"sort_empty"),s.fields){F(s,"fields") +const e=[] +s.fields.forEach(t=>{"string"==typeof t&&(t={field:t,weight:1}),e.push(t),i[t.field]="weight"in t?t.weight:1}),s.fields=e}return{options:s,query:e.toLowerCase().trim(),tokens:this.tokenize(e,s.respect_word_boundaries,i),total:0,items:[],weights:i,getAttrFn:s.nesting?I:A}}search(e,t){var i,s,n=this +s=this.prepareSearch(e,t),t=s.options,e=s.query +const o=t.score||n._getScoreFunction(s) +e.length?L(n.items,(e,n)=>{i=o(e),(!1===t.filter||i>0)&&s.items.push({score:i,id:n})}):L(n.items,(e,t)=>{s.items.push({score:1,id:t})}) +const r=n._getSortFunction(s) +return r&&s.items.sort(r),s.total=s.items.length,"number"==typeof t.limit&&(s.items=s.items.slice(0,t.limit)),s}}const P=e=>null==e?null:N(e),N=e=>"boolean"==typeof e?e?"1":"0":e+"",D=e=>(e+"").replace(/&/g,"&").replace(//g,">").replace(/"/g,"""),V=(e,t)=>{var i +return function(s,n){var o=this +i&&(o.loading=Math.max(o.loading-1,0),clearTimeout(i)),i=setTimeout(function(){i=null,o.loadedSearches[s]=!0,e.call(o,s,n)},t)}},j=(e,t,i)=>{var s,n=e.trigger,o={} +for(s of(e.trigger=function(){var i=arguments[0] +if(-1===t.indexOf(i))return n.apply(e,arguments) +o[i]=arguments},i.apply(e,[]),e.trigger=n,t))s in o&&n.apply(e,o[s])},$=(e,t=!1)=>{e&&(e.preventDefault(),t&&e.stopPropagation())},q=(e,t,i,s)=>{e.addEventListener(t,i,s)},R=(e,t)=>!!t&&(!!t[e]&&1===(t.altKey?1:0)+(t.ctrlKey?1:0)+(t.shiftKey?1:0)+(t.metaKey?1:0)),H=(e,t)=>{const i=e.getAttribute("id") +return i||(e.setAttribute("id",t),t)},M=e=>e.replace(/[\\"']/g,"\\$&"),z=(e,t)=>{t&&e.append(t)},B=(e,t)=>{if(Array.isArray(e))e.forEach(t) +else for(var i in e)e.hasOwnProperty(i)&&t(e[i],i)},K=e=>{if(e.jquery)return e[0] +if(e instanceof HTMLElement)return e +if(G(e)){var t=document.createElement("template") +return t.innerHTML=e.trim(),t.content.firstChild}return document.querySelector(e)},G=e=>"string"==typeof e&&e.indexOf("<")>-1,U=(e,t)=>{var i=document.createEvent("HTMLEvents") +i.initEvent(t,!0,!1),e.dispatchEvent(i)},W=(e,t)=>{Object.assign(e.style,t)},Q=(e,...t)=>{var i=X(t);(e=Y(e)).map(e=>{i.map(t=>{e.classList.add(t)})})},J=(e,...t)=>{var i=X(t);(e=Y(e)).map(e=>{i.map(t=>{e.classList.remove(t)})})},X=e=>{var t=[] +return B(e,e=>{"string"==typeof e&&(e=e.trim().split(/[\t\n\f\r\s]/)),Array.isArray(e)&&(t=t.concat(e))}),t.filter(Boolean)},Y=e=>(Array.isArray(e)||(e=[e]),e),Z=(e,t,i)=>{if(!i||i.contains(e))for(;e&&e.matches;){if(e.matches(t))return e +e=e.parentNode}},ee=(e,t=0)=>t>0?e[e.length-1]:e[0],te=(e,t)=>{if(!e)return-1 +t=t||e.nodeName +for(var i=0;e=e.previousElementSibling;)e.matches(t)&&i++ +return i},ie=(e,t)=>{B(t,(t,i)=>{null==t?e.removeAttribute(i):e.setAttribute(i,""+t)})},se=(e,t)=>{e.parentNode&&e.parentNode.replaceChild(t,e)},ne=(e,t)=>{if(null===t)return +if("string"==typeof t){if(!t.length)return +t=new RegExp(t,"i")}const i=e=>3===e.nodeType?(e=>{var i=e.data.match(t) +if(i&&e.data.length>0){var s=document.createElement("span") +s.className="highlight" +var n=e.splitText(i.index) +n.splitText(i[0].length) +var o=n.cloneNode(!0) +return s.appendChild(o),se(n,s),1}return 0})(e):((e=>{1!==e.nodeType||!e.childNodes||/(script|style)/i.test(e.tagName)||"highlight"===e.className&&"SPAN"===e.tagName||Array.from(e.childNodes).forEach(e=>{i(e)})})(e),0) +i(e)},oe="undefined"!=typeof navigator&&/Mac/.test(navigator.userAgent)?"metaKey":"ctrlKey" +var re={options:[],optgroups:[],plugins:[],delimiter:",",splitOn:null,persist:!0,diacritics:!0,create:null,createOnBlur:!1,createFilter:null,clearAfterSelect:!1,highlight:!0,openOnFocus:!0,shouldOpen:null,maxOptions:50,maxItems:null,hideSelected:null,duplicates:!1,addPrecedence:!1,selectOnTab:!1,preload:null,allowEmptyOption:!1,refreshThrottle:300,loadThrottle:300,loadingClass:"loading",dataAttr:null,optgroupField:"optgroup",valueField:"value",labelField:"text",disabledField:"disabled",optgroupLabelField:"label",optgroupValueField:"value",lockOptgroupOrder:!1,sortField:"$order",searchField:["text"],searchConjunction:"and",mode:null,wrapperClass:"ts-wrapper",controlClass:"ts-control",dropdownClass:"ts-dropdown",dropdownContentClass:"ts-dropdown-content",itemClass:"item",optionClass:"option",dropdownParent:null,controlInput:'',copyClassesToDropdown:!1,placeholder:null,hidePlaceholder:null,shouldLoad:function(e){return e.length>0},render:{}} +function le(e,t){var i=Object.assign({},re,t),s=i.dataAttr,n=i.labelField,o=i.valueField,r=i.disabledField,l=i.optgroupField,a=i.optgroupLabelField,c=i.optgroupValueField,d=e.tagName.toLowerCase(),u=e.getAttribute("placeholder")||e.getAttribute("data-placeholder") +if(!u&&!i.allowEmptyOption){let t=e.querySelector('option[value=""]') +t&&(u=t.textContent)}var p={placeholder:u,options:[],optgroups:[],items:[],maxItems:null} +return"select"===d?(()=>{var t,d=p.options,u={},h=1 +let g=0 +var f=e=>{var t=Object.assign({},e.dataset),i=s&&t[s] +return"string"==typeof i&&i.length&&(t=Object.assign(t,JSON.parse(i))),t},m=(e,t)=>{var s=P(e.value) +if(null!=s&&(s||i.allowEmptyOption)){if(u.hasOwnProperty(s)){if(t){var a=u[s][l] +a?Array.isArray(a)?a.push(t):u[s][l]=[a,t]:u[s][l]=t}}else{var c=f(e) +c[n]=c[n]||e.textContent,c[o]=c[o]||s,c[r]=c[r]||e.disabled,c[l]=c[l]||t,c.$option=e,c.$order=c.$order||++g,u[s]=c,d.push(c)}e.selected&&p.items.push(s)}} +p.maxItems=e.hasAttribute("multiple")?null:1,B(e.children,e=>{var i,s,n +"optgroup"===(t=e.tagName.toLowerCase())?((n=f(i=e))[a]=n[a]||i.getAttribute("label")||"",n[c]=n[c]||h++,n[r]=n[r]||i.disabled,n.$order=n.$order||++g,p.optgroups.push(n),s=n[c],B(i.children,e=>{m(e,s)})):"option"===t&&m(e)})})():(()=>{const t=e.getAttribute(s) +if(t)p.options=JSON.parse(t),B(p.options,e=>{p.items.push(e[o])}) +else{var r,l,a=null!=(r=null==e||null==(l=e.value)?void 0:l.trim())?r:"" +if(!i.allowEmptyOption&&!a.length)return +const t=a.split(i.delimiter) +B(t,e=>{const t={} +t[n]=e,t[o]=e,p.options.push(t)}),p.items=t}})(),Object.assign({},re,p,t)}var ae=0 +class ce extends(function(e){return e.plugins={},class extends e{constructor(...e){super(...e),this.plugins={names:[],settings:{},requested:{},loaded:{}}}static define(t,i){e.plugins[t]={name:t,fn:i}}initializePlugins(e){var t,i +const s=this,n=[] +if(Array.isArray(e))e.forEach(e=>{"string"==typeof e?n.push(e):(s.plugins.settings[e.name]=e.options,n.push(e.name))}) +else if(e)for(t in e)e.hasOwnProperty(t)&&(s.plugins.settings[t]=e[t],n.push(t)) +for(;i=n.shift();)s.require(i)}loadPlugin(t){var i=this,s=i.plugins,n=e.plugins[t] +if(!e.plugins.hasOwnProperty(t))throw new Error('Unable to find "'+t+'" plugin') +s.requested[t]=!0,s.loaded[t]=n.fn.apply(i,[i.plugins.settings[t]||{}]),s.names.push(t)}require(e){var t=this,i=t.plugins +if(!t.plugins.loaded.hasOwnProperty(e)){if(i.requested[e])throw new Error('Plugin has circular dependency ("'+e+'")') +t.loadPlugin(e)}return i.loaded[e]}}}(t)){constructor(e,t){var i +super(),this.order=0,this.isOpen=!1,this.isDisabled=!1,this.isReadOnly=!1,this.isInvalid=!1,this.isValid=!0,this.isLocked=!1,this.isFocused=!1,this.isInputHidden=!1,this.isSetup=!1,this.isDropdownContentStale=!0,this.ignoreFocus=!1,this.ignoreHover=!1,this.hasOptions=!1,this.lastValue="",this.caretPos=0,this.loading=0,this.loadedSearches={},this.activeOption=null,this.activeItems=[],this.optgroups={},this.options={},this.userOptions={},this.items=[],this.refreshTimeout=null,ae++ +var s=K(e) +if(s.tomselect)throw new Error("Tom Select already initialized on this element") +s.tomselect=this,i=(window.getComputedStyle&&window.getComputedStyle(s,null)).getPropertyValue("direction") +const n=le(s,t) +this.settings=n,this.input=s,this.tabIndex=s.tabIndex||0,this.is_select_tag="select"===s.tagName.toLowerCase(),this.rtl=/rtl/i.test(i),this.inputId=H(s,"tomselect-"+ae),this.isRequired=s.required,this.sifter=new T(this.options,{diacritics:n.diacritics}),n.mode=n.mode||(1===n.maxItems?"single":"multi"),"boolean"!=typeof n.hideSelected&&(n.hideSelected="multi"===n.mode),"boolean"!=typeof n.hidePlaceholder&&(n.hidePlaceholder="multi"!==n.mode) +var o=n.createFilter +"function"!=typeof o&&("string"==typeof o&&(o=new RegExp(o)),o instanceof RegExp?n.createFilter=e=>o.test(e):n.createFilter=e=>this.settings.duplicates||!this.options[e]),this.initializePlugins(n.plugins),this.setupCallbacks(),this.setupTemplates() +const r=K("
"),l=K("
"),a=this._render("dropdown"),c=K('
'),d=this.input.getAttribute("class")||"",u=n.mode +var p +if(Q(r,n.wrapperClass,d,u),Q(l,n.controlClass),z(r,l),Q(a,n.dropdownClass,u),n.copyClassesToDropdown&&Q(a,d),Q(c,n.dropdownContentClass),z(a,c),K(n.dropdownParent||r).appendChild(a),G(n.controlInput)){p=K(n.controlInput) +B(["autocorrect","autocapitalize","autocomplete","spellcheck","aria-label"],e=>{s.getAttribute(e)&&ie(p,{[e]:s.getAttribute(e)})}),p.tabIndex=-1,l.appendChild(p),this.focus_node=p}else n.controlInput?(p=K(n.controlInput),this.focus_node=p):(p=K(""),this.focus_node=l) +this.wrapper=r,this.dropdown=a,this.dropdown_content=c,this.control=l,this.control_input=p,this.setup()}setup(){const e=this,t=e.settings,i=e.control_input,s=e.dropdown,n=e.dropdown_content,o=e.wrapper,l=e.control,a=e.input,c=e.focus_node,d={passive:!0},u=e.inputId+"-ts-dropdown" +ie(n,{id:u}),ie(c,{role:"combobox","aria-haspopup":"listbox","aria-expanded":"false","aria-controls":u}) +const p=H(c,e.inputId+"-ts-control"),h="label[for='"+(e=>e.replace(/['"\\]/g,"\\$&"))(e.inputId)+"']",g=document.querySelector(h),f=e.focus.bind(e) +if(g){q(g,"click",f),ie(g,{for:p}) +const t=H(g,e.inputId+"-ts-label") +ie(c,{"aria-labelledby":t}),ie(n,{"aria-labelledby":t})}if(o.style.width=a.style.width,o.style.minWidth=a.style.minWidth,o.style.maxWidth=a.style.maxWidth,e.plugins.names.length){const t="plugin-"+e.plugins.names.join(" plugin-") +Q([o,s],t)}(null===t.maxItems||t.maxItems>1)&&e.is_select_tag&&ie(a,{multiple:"multiple"}),t.placeholder&&ie(i,{placeholder:t.placeholder}),!t.splitOn&&t.delimiter&&(t.splitOn=new RegExp("\\s*"+r(t.delimiter)+"+\\s*")),t.load&&t.loadThrottle&&(t.load=V(t.load,t.loadThrottle)),q(s,"mousemove",()=>{e.ignoreHover=!1}),q(s,"mouseenter",t=>{var i=Z(t.target,"[data-selectable]",s) +i&&e.onOptionHover(t,i)},{capture:!0}),q(s,"click",t=>{const i=Z(t.target,"[data-selectable]") +i&&(e.onOptionSelect(t,i),$(t,!0))}),q(l,"click",t=>{var s=Z(t.target,"[data-ts-item]",l) +s&&e.onItemSelect(t,s)?$(t,!0):""==i.value&&(e.onClick(),$(t,!0))}),q(c,"keydown",t=>e.onKeyDown(t)),q(i,"keypress",t=>e.onKeyPress(t)),q(i,"input",t=>e.onInput(t)),q(c,"blur",t=>e.onBlur(t)),q(c,"focus",t=>e.onFocus(t)),q(i,"paste",t=>e.onPaste(t)) +const m=t=>{const n=t.composedPath()[0] +if(!o.contains(n)&&!s.contains(n))return e.isFocused&&e.blur(),void e.inputState() +n==i&&e.isOpen?t.stopPropagation():$(t,!0)},v=()=>{e.isOpen&&e.positionDropdown()},O=()=>{e.isValid&&(e.isValid=!1,e.isInvalid=!0,e.refreshState())} +q(a,"invalid",O),q(document,"mousedown",m),q(window,"scroll",v,d),q(window,"resize",v,d),this._destroy=()=>{a.removeEventListener("invalid",O),document.removeEventListener("mousedown",m),window.removeEventListener("scroll",v),window.removeEventListener("resize",v),g&&g.removeEventListener("click",f)},this.revertSettings={innerHTML:a.innerHTML,tabIndex:a.tabIndex},a.tabIndex=-1,a.insertAdjacentElement("afterend",e.wrapper),e.sync(!1),t.items=[],delete t.optgroups,delete t.options,e.refreshItems(),e.close(!1),e.inputState(),e.isSetup=!0,e.on("change",this.onChange),Q(a,"tomselected","ts-hidden-accessible"),e.trigger("initialize"),!0===t.preload&&e.preload()}setupOptions(e=[],t=[]){this.addOptions(e),B(t,e=>{this.registerOptionGroup(e)})}setupTemplates(){var e=this,t=e.settings.labelField,i=e.settings.optgroupLabelField,s={optgroup:e=>{let t=document.createElement("div") +return t.className="optgroup",t.appendChild(e.options),t},optgroup_header:(e,t)=>'
'+t(e[i])+"
",option:(e,i)=>"
"+i(e[t])+"
",item:(e,i)=>"
"+i(e[t])+"
",option_create:(e,t)=>'
Add '+t(e.input)+"
",no_results:()=>'
No results found
',loading:()=>'
',not_loading:()=>{},dropdown:()=>"
"} +e.settings.render=Object.assign({},s,e.settings.render)}setupCallbacks(){var e,t,i={initialize:"onInitialize",change:"onChange",item_add:"onItemAdd",item_remove:"onItemRemove",item_select:"onItemSelect",clear:"onClear",option_add:"onOptionAdd",option_remove:"onOptionRemove",option_clear:"onOptionClear",optgroup_add:"onOptionGroupAdd",optgroup_remove:"onOptionGroupRemove",optgroup_clear:"onOptionGroupClear",dropdown_open:"onDropdownOpen",dropdown_close:"onDropdownClose",type:"onType",load:"onLoad",focus:"onFocus",blur:"onBlur"} +for(e in i)(t=this.settings[i[e]])&&this.on(e,t)}sync(e=!0){const t=this,i=e?le(t.input,{delimiter:t.settings.delimiter,allowEmptyOption:t.settings.allowEmptyOption}):t.settings +t.setupOptions(i.options,i.optgroups),t.setValue(i.items||[],!0),t.input.disabled?t.disable():t.input.readOnly?t.setReadOnly(!0):t.enable(),t.lastQuery=null}onClick(){var e=this +if(e.activeItems.length>0)return e.clearActiveItems(),void e.focus() +e.isFocused&&e.isOpen?e.blur():e.focus()}onMouseDown(){}onChange(){U(this.input,"input"),U(this.input,"change")}onPaste(e){var t=this +t.isInputHidden||t.isLocked?$(e):t.settings.splitOn&&setTimeout(()=>{var e=t.inputValue() +if(e.match(t.settings.splitOn)){var i=e.trim().split(t.settings.splitOn) +B(i,e=>{P(e)&&(this.options[e]?t.addItem(e):t.createItem(e))})}},0)}onKeyPress(e){var t=this +if(!t.isLocked){var i=String.fromCharCode(e.keyCode||e.which) +return t.settings.create&&"multi"===t.settings.mode&&i===t.settings.delimiter?(t.createItem(),void $(e)):void 0}$(e)}onKeyDown(e){var t=this +if(t.ignoreHover=!0,t.isLocked)9!==e.keyCode&&$(e) +else{switch(e.keyCode){case 65:if(R(oe,e)&&""==t.control_input.value)return $(e),void t.selectAll() +break +case 27:return t.isOpen&&($(e,!0),t.close()),void t.clearActiveItems() +case 40:if(!t.isOpen&&t.hasOptions)t.open() +else if(t.activeOption){let e=t.getAdjacent(t.activeOption,1) +e&&t.setActiveOption(e)}return void $(e) +case 38:if(t.activeOption){let e=t.getAdjacent(t.activeOption,-1) +e&&t.setActiveOption(e)}return void $(e) +case 13:return void(t.canSelect(t.activeOption)?(t.onOptionSelect(e,t.activeOption),$(e)):(t.settings.create&&t.createItem()||document.activeElement==t.control_input&&t.isOpen)&&$(e)) +case 37:return void t.advanceSelection(-1,e) +case 39:return void t.advanceSelection(1,e) +case 9:return void(t.settings.selectOnTab&&(t.canSelect(t.activeOption)?(t.onOptionSelect(e,t.activeOption),$(e)):t.settings.create&&t.createItem()&&$(e))) +case 8:case 46:return void t.deleteSelection(e)}t.isInputHidden&&!R(oe,e)&&$(e)}}onInput(e){if(this.isLocked)return +const t=this.inputValue() +this.lastValue!==t&&(this.lastValue=t,""!=t?(this.refreshTimeout&&window.clearTimeout(this.refreshTimeout),this.refreshTimeout=((e,t)=>t>0?window.setTimeout(e,t):(e.call(null),null))(()=>{this.refreshTimeout=null,this._onInput()},this.settings.refreshThrottle)):this._onInput())}_onInput(){const e=this.lastValue +this.settings.shouldLoad.call(this,e)&&this.load(e),this.refreshOptions(),this.trigger("type",e)}onOptionHover(e,t){this.ignoreHover||this.setActiveOption(t,!1)}onFocus(e){var t=this,i=t.isFocused +if(t.isDisabled||t.isReadOnly)return t.blur(),void $(e) +t.ignoreFocus||(t.isFocused=!0,"focus"===t.settings.preload&&t.preload(),i||t.trigger("focus"),t.activeItems.length||(t.inputState(),t.refreshOptions(!!t.settings.openOnFocus)),t.refreshState())}onBlur(e){if(!1!==document.hasFocus()){var t=this +if(t.isFocused){t.isFocused=!1,t.ignoreFocus=!1 +var i=()=>{t.close(),t.setActiveItem(),t.setCaret(t.items.length),t.trigger("blur")} +t.settings.create&&t.settings.createOnBlur?t.createItem(null,i):i()}}}onOptionSelect(e,t){var i,s=this +t.parentElement&&t.parentElement.matches("[data-disabled]")||(t.classList.contains("create")?s.createItem(null,()=>{s.settings.closeAfterSelect?s.close():s.settings.clearAfterSelect&&s.setTextboxValue()}):void 0!==(i=t.dataset.value)&&(s.isDropdownContentStale=s.settings.hideSelected,s.addItem(i),s.settings.closeAfterSelect?s.close():s.settings.clearAfterSelect&&s.setTextboxValue(),!s.settings.hideSelected&&e.type&&/click/.test(e.type)&&s.setActiveOption(t)))}canSelect(e){return!!(this.isOpen&&e&&this.dropdown_content.contains(e))}onItemSelect(e,t){var i=this +return!i.isLocked&&"multi"===i.settings.mode&&($(e),i.setActiveItem(t,e),!0)}canLoad(e){return!!this.settings.load&&!this.loadedSearches.hasOwnProperty(e)}load(e){const t=this +if(!t.canLoad(e))return +Q(t.wrapper,t.settings.loadingClass),t.loading++ +const i=t.loadCallback.bind(t) +t.settings.load.call(t,e,i)}loadCallback(e,t){const i=this +i.loading=Math.max(i.loading-1,0),i.isDropdownContentStale=!0,i.clearActiveOption(),i.setupOptions(e,t),i.refreshOptions(i.isFocused&&!i.isInputHidden),i.loading||J(i.wrapper,i.settings.loadingClass),i.trigger("load",e,t)}preload(){var e=this.wrapper.classList +e.contains("preloaded")||(e.add("preloaded"),this.load(""))}setTextboxValue(e=""){var t=this.control_input +t.value!==e&&(t.value=e,U(t,"update"),this.lastValue=e)}getValue(){return this.is_select_tag&&this.input.hasAttribute("multiple")?this.items:this.items.join(this.settings.delimiter)}setValue(e,t){j(this,t?[]:["change"],()=>{this.clear(t),this.addItems(e,t)})}setMaxItems(e){0===e&&(e=null),this.settings.maxItems=e,this.refreshState()}setActiveItem(e,t){var i,s,n,o,r,l,a=this +if("single"!==a.settings.mode){if(!e)return a.clearActiveItems(),void(a.isFocused&&a.inputState()) +if("click"===(i=t&&t.type.toLowerCase())&&R("shiftKey",t)&&a.activeItems.length){for(l=a.getLastActive(),(n=Array.prototype.indexOf.call(a.control.children,l))>(o=Array.prototype.indexOf.call(a.control.children,e))&&(r=n,n=o,o=r),s=n;s<=o;s++)e=a.control.children[s],-1===a.activeItems.indexOf(e)&&a.setActiveItemClass(e) +$(t)}else"click"===i&&R(oe,t)||"keydown"===i&&R("shiftKey",t)?e.classList.contains("active")?a.removeActiveItem(e):a.setActiveItemClass(e):(a.clearActiveItems(),a.setActiveItemClass(e)) +a.inputState(),a.isFocused||a.focus()}}setActiveItemClass(e){const t=this,i=t.control.querySelector(".last-active") +i&&J(i,"last-active"),Q(e,"active last-active"),t.trigger("item_select",e),-1==t.activeItems.indexOf(e)&&t.activeItems.push(e)}removeActiveItem(e){var t=this.activeItems.indexOf(e) +this.activeItems.splice(t,1),J(e,"active")}clearActiveItems(){J(this.activeItems,"active"),this.activeItems=[]}setActiveOption(e,t=!0){e!==this.activeOption&&(this.clearActiveOption(),e&&(this.activeOption=e,ie(this.focus_node,{"aria-activedescendant":e.getAttribute("id")}),ie(e,{"aria-selected":"true"}),Q(e,"active"),t&&this.scrollToOption(e)))}scrollToOption(e,t){if(!e)return +const i=this.dropdown_content,s=i.clientHeight,n=i.scrollTop||0,o=e.offsetHeight,r=e.getBoundingClientRect().top-i.getBoundingClientRect().top+n +r+o>s+n?this.scroll(r-s+o,t):r{e.setActiveItemClass(t)}))}inputState(){var e=this +e.control.contains(e.control_input)&&(ie(e.control_input,{placeholder:e.settings.placeholder}),e.activeItems.length>0||!e.isFocused&&e.settings.hidePlaceholder&&e.items.length>0?(e.setTextboxValue(),e.isInputHidden=!0):(e.settings.hidePlaceholder&&e.items.length>0&&ie(e.control_input,{placeholder:""}),e.isInputHidden=!1),e.wrapper.classList.toggle("input-hidden",e.isInputHidden))}inputValue(){return this.control_input.value.trim()}focus(){var e=this +if(e.isDisabled||e.isReadOnly)return +e.ignoreFocus=!0 +const t=this.control_input.offsetWidth?this.control_input:this.focus_node +t.focus(),setTimeout(()=>{e.ignoreFocus=!1 +t.getRootNode().activeElement===t&&this.onFocus()},0)}blur(){this.focus_node.blur(),this.onBlur()}getScoreFunction(e){return this.sifter.getScoreFunction(e,this.getSearchOptions())}getSearchOptions(){var e=this.settings,t=e.sortField +return"string"==typeof e.sortField&&(t=[{field:e.sortField}]),{fields:e.searchField,conjunction:e.searchConjunction,sort:t,nesting:e.nesting}}search(e){var t,i,s=this,n=this.getSearchOptions() +if(s.settings.score&&"function"!=typeof(i=s.settings.score.call(s,e)))throw new Error('Tom Select "score" setting must be a function that returns a function') +return s.isDropdownContentStale||e!==s.lastQuery?(s.lastQuery=e,/(.)\1{15,}/.test(e)&&(e=""),t=s.sifter.search(e,Object.assign(n,{score:i})),s.currentResults=t):t=Object.assign({},s.currentResults),s.settings.hideSelected&&(t.items=t.items.filter(e=>{let t=P(e.id) +return!(null!==t&&-1!==s.items.indexOf(t))})),t}refreshOptions(e=!0){var t,i,s,n,o,r,l,a,c,d +const u={},p=[] +var h=this,g=h.inputValue() +const f=g===h.lastQuery||""==g&&null==h.lastQuery +var m=h.search(g),v=null,O=h.settings.shouldOpen||!1,b=h.dropdown_content +f&&(v=h.activeOption)&&(c=v.closest("[data-group]")),n=m.items.length,"number"==typeof h.settings.maxOptions&&(n=Math.min(n,h.settings.maxOptions)),n>0&&(O=!0) +const y=(e,t)=>{let i=u[e] +if(void 0!==i){let e=p[i] +if(void 0!==e)return[i,e.fragment]}let s=document.createDocumentFragment() +return i=p.length,p.push({fragment:s,order:t,optgroup:e}),[i,s]} +for(t=0;t0&&(d=d.cloneNode(!0),ie(d,{id:l.$id+"-clone-"+i,"aria-selected":null}),d.classList.add("ts-cloned"),J(d,"active"),h.activeOption&&h.activeOption.dataset.value==n&&c&&c.dataset.group===o.toString()&&(v=d)),a.appendChild(d),""!=o&&(u[o]=s)}}var S +h.settings.lockOptgroupOrder&&p.sort((e,t)=>e.order-t.order),l=document.createDocumentFragment(),B(p,e=>{let t=e.fragment,i=e.optgroup +if(!t||!t.children.length)return +let s=h.optgroups[i] +if(void 0!==s){let e=document.createDocumentFragment(),i=h.render("optgroup_header",s) +z(e,i),z(e,t) +let n=h.render("optgroup",{group:s,options:e}) +z(l,n)}else z(l,t)}),b.innerHTML="",z(b,l),h.isDropdownContentStale=!1,h.settings.highlight&&(S=b.querySelectorAll("span.highlight"),Array.prototype.forEach.call(S,function(e){var t=e.parentNode +t.replaceChild(e.firstChild,e),t.normalize()}),m.query.length&&m.tokens.length&&B(m.tokens,e=>{ne(b,e.regex)})) +var _=e=>{let t=h.render(e,{input:g}) +return t&&(O=!0,b.insertBefore(t,b.firstChild)),t} +if(h.loading?_("loading"):h.settings.shouldLoad.call(h,g)?0===m.items.length&&_("no_results"):_("not_loading"),(a=h.canCreate(g))&&(d=_("option_create")),h.hasOptions=m.items.length>0||a,O){if(m.items.length>0){if(v||"single"!==h.settings.mode||null==h.items[0]||(v=h.getOption(h.items[0])),!b.contains(v)){let e=0 +d&&!h.settings.addPrecedence&&(e=1),v=h.selectable()[e]}}else d&&(v=d) +e&&!h.isOpen&&(h.open(),h.scrollToOption(v,"auto")),h.setActiveOption(v)}else h.clearActiveOption(),e&&h.isOpen&&h.close(!1)}selectable(){return this.dropdown_content.querySelectorAll("[data-selectable]")}addOption(e,t=!1){const i=this +if(Array.isArray(e))return i.addOptions(e,t),!1 +const s=P(e[i.settings.valueField]) +return null===s||i.options.hasOwnProperty(s)?(i.updateOption(e[i.settings.valueField],e),!1):(e.$order=e.$order||++i.order,e.$id=i.inputId+"-opt-"+e.$order,i.options[s]=e,i.isDropdownContentStale=!0,t&&(i.userOptions[s]=t,i.trigger("option_add",s,e)),s)}addOptions(e,t=!1){B(e,e=>{this.addOption(e,t)})}registerOption(e){return this.addOption(e)}registerOptionGroup(e){var t=P(e[this.settings.optgroupValueField]) +return null!==t&&(e.$order=e.$order||++this.order,this.optgroups[t]=e,t)}addOptionGroup(e,t){var i +t[this.settings.optgroupValueField]=e,(i=this.registerOptionGroup(t))&&this.trigger("optgroup_add",i,t)}removeOptionGroup(e){this.optgroups.hasOwnProperty(e)&&(delete this.optgroups[e],this.clearCache(),this.trigger("optgroup_remove",e))}clearOptionGroups(){this.optgroups={},this.clearCache(),this.trigger("optgroup_clear")}updateOption(e,t){const i=this +var s,n +const o=P(e),r=P(t[i.settings.valueField]) +if(null===o)return +const l=i.options[o] +if(null==l)return +if("string"!=typeof r)throw new Error("Value must be set in option data") +const a=i.getOption(o),c=i.getItem(o) +if(t.$order=t.$order||l.$order,delete i.options[o],i.uncacheValue(r),i.options[r]=t,a){if(i.dropdown_content.contains(a)){const e=i._render("option",t) +se(a,e),i.activeOption===a&&i.setActiveOption(e)}a.remove()}c&&(-1!==(n=i.items.indexOf(o))&&i.items.splice(n,1,r),s=i._render("item",t),c.classList.contains("active")&&Q(s,"active"),se(c,s)),i.isDropdownContentStale=!0}removeOption(e,t){const i=this +e=N(e),i.uncacheValue(e),delete i.userOptions[e],delete i.options[e],i.isDropdownContentStale=!0,i.trigger("option_remove",e),i.removeItem(e,t)}clearOptions(e){const t=(e||this.clearFilter).bind(this) +this.loadedSearches={},this.userOptions={},this.clearCache() +const i={} +B(this.options,(e,s)=>{t(e,s)&&(i[s]=e)}),this.options=this.sifter.items=i,this.isDropdownContentStale=!0,this.trigger("option_clear")}clearFilter(e,t){return this.items.indexOf(t)>=0}getOption(e,t=!1){const i=P(e) +if(null===i)return null +const s=this.options[i] +if(null!=s){if(s.$div)return s.$div +if(t)return this._render("option",s)}return null}getAdjacent(e,t,i="option"){var s +if(!e)return null +s="item"==i?this.controlChildren():this.dropdown_content.querySelectorAll("[data-selectable]") +for(let i=0;i0?s[i+1]:s[i-1] +return null}getItem(e){if("object"==typeof e)return e +var t=P(e) +return null!==t?this.control.querySelector(`[data-value="${M(t)}"]`):null}addItems(e,t){var i=this,s=Array.isArray(e)?e:[e] +const n=(s=s.filter(e=>-1===i.items.indexOf(e)))[s.length-1] +s.forEach(e=>{i.isPending=e!==n,i.addItem(e,t)})}addItem(e,t){j(this,t?[]:["change","dropdown_close"],()=>{var i,s +const n=this,o=n.settings.mode,r=P(e) +if((!r||-1===n.items.indexOf(r)||("single"===o&&n.close(),"single"!==o&&n.settings.duplicates))&&null!==r&&n.options.hasOwnProperty(r)&&("single"===o&&n.clear(t),"multi"!==o||!n.isFull())){if(i=n._render("item",n.options[r]),n.control.contains(i)&&(i=i.cloneNode(!0)),s=n.isFull(),n.items.splice(n.caretPos,0,r),n.insertAtCaret(i),n.isSetup){if(!n.isPending&&n.settings.hideSelected){let e=n.getOption(r),t=n.getAdjacent(e,1) +t&&n.setActiveOption(t)}n.settings.clearAfterSelect&&n.setTextboxValue(),n.isPending||n.settings.closeAfterSelect||n.refreshOptions(n.isFocused&&"single"!==o),0!=n.settings.closeAfterSelect&&n.isFull()?n.close():n.isPending||n.positionDropdown(),n.trigger("item_add",r,i),n.isPending||n.updateOriginalInput({silent:t})}(!n.isPending||!s&&n.isFull())&&(n.inputState(),n.refreshState())}})}removeItem(e=null,t){const i=this +if(!(e=i.getItem(e)))return +var s,n +const o=e.dataset.value +s=te(e),e.remove(),e.classList.contains("active")&&(n=i.activeItems.indexOf(e),i.activeItems.splice(n,1),J(e,"active")),i.items.splice(s,1),i.isDropdownContentStale=!0,!i.settings.persist&&i.userOptions.hasOwnProperty(o)&&i.removeOption(o,t),s{}){3===arguments.length&&(t=arguments[2]),"function"!=typeof t&&(t=()=>{}) +var i,s=this,n=s.caretPos +if(e=e||s.inputValue(),!s.canCreate(e)){return P(e)&&this.options[e]&&s.addItem(e),t(),!1}s.lock() +var o=!1,r=e=>{if(s.unlock(),!e||"object"!=typeof e)return t() +var i=P(e[s.settings.valueField]) +if("string"!=typeof i)return t() +s.setTextboxValue(),s.addOption(e,!0),s.setCaret(n),s.addItem(i),t(e),o=!0} +return i="function"==typeof s.settings.create?s.settings.create.call(this,e,r):{[s.settings.labelField]:e,[s.settings.valueField]:e},o||r(i),!0}refreshItems(){var e=this +e.isDropdownContentStale=!0,e.isSetup&&e.addItems(e.items),e.updateOriginalInput(),e.refreshState()}refreshState(){const e=this +e.refreshValidityState() +const t=e.isFull(),i=e.isLocked +e.wrapper.classList.toggle("rtl",e.rtl) +const s=e.wrapper.classList +var n +s.toggle("focus",e.isFocused),s.toggle("disabled",e.isDisabled),s.toggle("readonly",e.isReadOnly),s.toggle("required",e.isRequired),s.toggle("invalid",!e.isValid),s.toggle("locked",i),s.toggle("full",t),s.toggle("input-active",e.isFocused&&!e.isInputHidden),s.toggle("dropdown-active",e.isOpen),s.toggle("has-options",(n=e.options,0===Object.keys(n).length)),s.toggle("has-items",e.items.length>0)}refreshValidityState(){var e=this +e.input.validity&&(e.isValid=e.input.validity.valid,e.isInvalid=!e.isValid)}isFull(){return null!==this.settings.maxItems&&this.items.length>=this.settings.maxItems}updateOriginalInput(e={}){const t=this +var i,s +const n=t.input.querySelector('option[value=""]') +if(t.is_select_tag){const o=[],r=t.input.querySelectorAll("option:checked").length +function l(e,i,s){return e||(e=K('")),e!=n&&t.input.append(e),o.push(e),(e!=n||r>0||"multi"==t.settings.mode)&&(e.selected=!0),e}t.input.querySelectorAll("option:checked").forEach(e=>{e.selected=!1}),0==t.items.length&&"single"==t.settings.mode?l(n,"",""):t.items.forEach(e=>{if(i=t.options[e],s=i[t.settings.labelField]||"",o.includes(i.$option)){l(t.input.querySelector(`option[value="${M(e)}"]:not(:checked)`),e,s)}else i.$option=l(i.$option,e,s)})}else t.input.value=t.getValue() +t.isSetup&&(e.silent||t.trigger("change",t.getValue()))}open(){var e=this +e.isLocked||e.isOpen||"multi"===e.settings.mode&&e.isFull()||(e.isOpen=!0,ie(e.focus_node,{"aria-expanded":"true"}),e.refreshState(),W(e.dropdown,{visibility:"hidden",display:"block"}),e.positionDropdown(),W(e.dropdown,{visibility:"visible",display:"block"}),e.focus(),e.trigger("dropdown_open",e.dropdown))}close(e=!0){var t=this,i=t.isOpen +e&&(t.setTextboxValue(),"single"===t.settings.mode&&t.items.length&&t.inputState()),t.isOpen=!1,ie(t.focus_node,{"aria-expanded":"false"}),W(t.dropdown,{display:"none"}),t.settings.hideSelected&&t.clearActiveOption(),t.refreshState(),i&&t.trigger("dropdown_close",t.dropdown)}positionDropdown(){if("body"===this.settings.dropdownParent){var e=this.control,t=e.getBoundingClientRect(),i=e.offsetHeight+t.top+window.scrollY,s=t.left+window.scrollX +W(this.dropdown,{width:t.width+"px",top:i+"px",left:s+"px"})}}clear(e){var t=this +if(t.items.length){var i=t.controlChildren() +B(i,e=>{t.removeItem(e,!0)}),t.inputState(),e||t.updateOriginalInput(),t.trigger("clear")}}insertAtCaret(e){const t=this,i=t.caretPos,s=t.control +s.insertBefore(e,s.children[i]||null),t.setCaret(i+1)}deleteSelection(e){var t,i,s,n,o,r=this +t=e&&8===e.keyCode?-1:1,i={start:(o=r.control_input).selectionStart||0,length:(o.selectionEnd||0)-(o.selectionStart||0)} +const l=[] +if(r.activeItems.length)n=ee(r.activeItems,t),s=te(n),t>0&&s++,B(r.activeItems,e=>l.push(e)) +else if((r.isFocused||"single"===r.settings.mode)&&r.items.length){const e=r.controlChildren() +let s +t<0&&0===i.start&&0===i.length?s=e[r.caretPos-1]:t>0&&i.start===r.inputValue().length&&(s=e[r.caretPos]),void 0!==s&&l.push(s)}if(!r.shouldDelete(l,e))return!1 +for($(e,!0),void 0!==s&&r.setCaret(s);l.length;)r.removeItem(l.pop()) +return r.inputState(),r.positionDropdown(),r.refreshOptions(!1),!0}shouldDelete(e,t){const i=e.map(e=>e.dataset.value) +return!(!i.length||"function"==typeof this.settings.onDelete&&!1===this.settings.onDelete.call(this,i,t))}advanceSelection(e,t){var i,s,n=this +n.rtl&&(e*=-1),n.inputValue().length||(R(oe,t)||R("shiftKey",t)?(s=(i=n.getLastActive(e))?i.classList.contains("active")?n.getAdjacent(i,e,"item"):i:e>0?n.control_input.nextElementSibling:n.control_input.previousElementSibling)&&(s.classList.contains("active")&&n.removeActiveItem(i),n.setActiveItemClass(s)):n.moveCaret(e))}moveCaret(e){}getLastActive(e){let t=this.control.querySelector(".last-active") +if(t)return t +var i=this.control.querySelectorAll(".active") +return i?ee(i,e):void 0}setCaret(e){this.caretPos=this.items.length}controlChildren(){return Array.from(this.control.querySelectorAll("[data-ts-item]"))}lock(){this.setLocked(!0)}unlock(){this.setLocked(!1)}setLocked(e=this.isReadOnly||this.isDisabled){this.isLocked=e,this.refreshState()}disable(){this.setDisabled(!0),this.close()}enable(){this.setDisabled(!1)}setDisabled(e){this.focus_node.tabIndex=e?-1:this.tabIndex,this.isDisabled=e,this.input.disabled=e,this.control_input.disabled=e,this.setLocked()}setReadOnly(e){this.isReadOnly=e,this.input.readOnly=e,this.control_input.readOnly=e,this.setLocked()}destroy(){var e=this,t=e.revertSettings +e.trigger("destroy"),e.off(),e.wrapper.remove(),e.dropdown.remove(),e.input.innerHTML=t.innerHTML,e.input.tabIndex=t.tabIndex,J(e.input,"tomselected","ts-hidden-accessible"),e._destroy(),delete e.input.tomselect}render(e,t){var i,s +const n=this +if("function"!=typeof this.settings.render[e])return null +if(!(s=n.settings.render[e].call(this,t,D)))return null +if(s=K(s),"option"===e||"option_create"===e?t[n.settings.disabledField]?ie(s,{"aria-disabled":"true"}):ie(s,{"data-selectable":""}):"optgroup"===e&&(i=t.group[n.settings.optgroupValueField],ie(s,{"data-group":i}),t.group[n.settings.disabledField]&&ie(s,{"data-disabled":""})),"option"===e||"item"===e){const i=N(t[n.settings.valueField]) +ie(s,{"data-value":i}),"item"===e?(Q(s,n.settings.itemClass),ie(s,{"data-ts-item":""})):(Q(s,n.settings.optionClass),ie(s,{role:"option",id:t.$id}),t.$div=s,n.options[i]=t)}return s}_render(e,t){const i=this.render(e,t) +if(null==i)throw"HTMLElement expected" +return i}clearCache(){B(this.options,e=>{e.$div&&(e.$div.remove(),delete e.$div)})}uncacheValue(e){const t=this.getOption(e) +t&&t.remove()}canCreate(e){return this.settings.create&&e.length>0&&this.settings.createFilter.call(this,e)}hook(e,t,i){var s=this,n=s[t] +s[t]=function(){var t,o +return"after"===e&&(t=n.apply(s,arguments)),o=i.apply(s,arguments),"instead"===e?o:("before"===e&&(t=n.apply(s,arguments)),t)}}}return ce.define("change_listener",function(){q(this.input,"change",()=>{this.sync()})}),ce.define("checkbox_options",function(e){var t=this,i=t.onOptionSelect +t.settings.hideSelected=!1 +const s=Object.assign({className:"tomselect-checkbox",checkedClassNames:void 0,uncheckedClassNames:void 0},e) +var n=function(e,t){t?(e.checked=!0,s.uncheckedClassNames&&e.classList.remove(...s.uncheckedClassNames),s.checkedClassNames&&e.classList.add(...s.checkedClassNames)):(e.checked=!1,s.checkedClassNames&&e.classList.remove(...s.checkedClassNames),s.uncheckedClassNames&&e.classList.add(...s.uncheckedClassNames))},o=function(e){setTimeout(()=>{var t=e.querySelector("input."+s.className) +t instanceof HTMLInputElement&&n(t,e.classList.contains("selected"))},1)} +t.hook("after","setupTemplates",()=>{var e=t.settings.render.option +t.settings.render.option=(i,o)=>{var r=K(e.call(t,i,o)),l=document.createElement("input") +s.className&&l.classList.add(s.className),l.addEventListener("click",function(e){$(e)}),l.type="checkbox" +const a=P(i[t.settings.valueField]) +return n(l,!!(a&&t.items.indexOf(a)>-1)),r.prepend(l),r}}),t.on("item_remove",e=>{var i=t.getOption(e) +i&&(i.classList.remove("selected"),o(i))}),t.on("item_add",e=>{var i=t.getOption(e) +i&&o(i)}),t.hook("instead","onOptionSelect",(e,s)=>{if(s.classList.contains("selected"))return s.classList.remove("selected"),t.removeItem(s.dataset.value),t.refreshOptions(),void $(e,!0) +i.call(t,e,s),o(s)})}),ce.define("clear_button",function(e){const t=this,i=Object.assign({className:"clear-button",title:"Clear All",role:"button",tabindex:0,html:e=>`
×
`},e) +t.on("initialize",()=>{var e=K(i.html(i)) +e.addEventListener("click",e=>{t.isLocked||(t.clear(),"single"===t.settings.mode&&t.settings.allowEmptyOption&&t.addItem(""),t.refreshOptions(!1),e.preventDefault(),e.stopPropagation())}),t.control.appendChild(e)})}),ce.define("drag_drop",function(){var e=this +if("multi"!==e.settings.mode)return +var t=e.lock,i=e.unlock +let s,n=!0 +e.hook("after","setupTemplates",()=>{var t=e.settings.render.item +e.settings.render.item=(i,o)=>{const r=K(t.call(e,i,o)) +ie(r,{draggable:"true"}) +const l=e=>{e.preventDefault(),r.classList.add("ts-drag-over"),a(r,s)},a=(e,t)=>{var i,s,n +void 0!==t&&(((e,t)=>{do{var i +if(e==(t=null==(i=t)?void 0:i.previousElementSibling))return!0}while(t&&t.previousElementSibling) +return!1})(t,r)?(s=t,null==(n=(i=e).parentNode)||n.insertBefore(s,i.nextSibling)):((e,t)=>{var i +null==(i=e.parentNode)||i.insertBefore(t,e)})(e,t))} +return q(r,"mousedown",e=>{n||$(e),e.stopPropagation()}),q(r,"dragstart",e=>{s=r,setTimeout(()=>{r.classList.add("ts-dragging")},0)}),q(r,"dragenter",l),q(r,"dragover",l),q(r,"dragleave",()=>{r.classList.remove("ts-drag-over")}),q(r,"dragend",()=>{var t +document.querySelectorAll(".ts-drag-over").forEach(e=>e.classList.remove("ts-drag-over")),null==(t=s)||t.classList.remove("ts-dragging"),s=void 0 +var i=[] +e.control.querySelectorAll("[data-value]").forEach(e=>{if(e.dataset.value){let t=e.dataset.value +t&&i.push(t)}}),e.setValue(i)}),r}}),e.hook("instead","lock",()=>(n=!1,t.call(e))),e.hook("instead","unlock",()=>(n=!0,i.call(e)))}),ce.define("dropdown_header",function(e){const t=this,i=Object.assign({title:"Untitled",headerClass:"dropdown-header",titleRowClass:"dropdown-header-title",labelClass:"dropdown-header-label",closeClass:"dropdown-header-close",html:e=>'
'+e.title+'×
'},e) +t.on("initialize",()=>{var e=K(i.html(i)),s=e.querySelector("."+i.closeClass) +s&&s.addEventListener("click",e=>{$(e,!0),t.close()}),t.dropdown.insertBefore(e,t.dropdown.firstChild)})}),ce.define("caret_position",function(){var e=this +e.hook("instead","setCaret",t=>{"single"!==e.settings.mode&&e.control.contains(e.control_input)?(t=Math.max(0,Math.min(e.items.length,t)))==e.caretPos||e.isPending||e.controlChildren().forEach((i,s)=>{s{if(!e.isFocused)return +const i=e.getLastActive(t) +if(i){const s=te(i) +e.setCaret(t>0?s+1:s),e.setActiveItem(),J(i,"last-active")}else e.setCaret(e.caretPos+t)})}),ce.define("dropdown_input",function(){const e=this +e.settings.shouldOpen=!0,e.hook("before","setup",()=>{var t +e.focus_node=e.control,Q(e.control_input,"dropdown-input") +const i=K('