From ec1b77e8ab27465abc9bddc11fd1a99c0fc794c0 Mon Sep 17 00:00:00 2001 From: antoineatrhea Date: Tue, 3 Oct 2023 10:38:58 +0200 Subject: [PATCH] Fix #457: Supports of Blazor Server --- .../COMET.Web.Common.Tests.csproj | 23 + .../Components/DashboardTestFixture.cs | 6 +- .../Components/IndexComponentTestFixture.cs | 8 +- .../Components/LoginTestFixture.cs | 6 +- .../Components/OpenModelTestFixture.cs | 4 +- ...IterationApplicationTemplateTestFixture.cs | 4 +- .../Data/DefaultTextConfiguration.json | 12 + .../DefaultTextConfiguration.json | 12 + .../ConfigurationServiceTestFixture.cs | 74 ++ .../StringTableServiceTestFixture.cs | 58 ++ .../ConfigurationServiceTestFixture.cs | 50 +- .../ServerConnectionServiceTestFixture.cs | 8 +- .../Shared/TopMenuTestFixture.cs | 6 +- COMET.Web.Common/COMET.Web.Common.csproj | 2 +- .../Components/Dashboard.razor.cs | 6 +- COMET.Web.Common/Components/Login.razor.cs | 1 - .../Components/OpenModel.razor.cs | 6 +- .../DateTimeParameterTypeEditor.razor | 23 +- ...ingleIterationApplicationTemplate.razor.cs | 6 +- .../ValueSetRenderers/ValueArrayDetails.razor | 48 +- .../Extensions/ServiceCollectionExtensions.cs | 105 +++ ...nsions.cs => ServiceProviderExtensions.cs} | 119 +-- .../WebAssemblyHostBuilderExtensions.cs | 113 --- .../ConfigurationService.cs | 78 ++ .../StringTableService/StringTableService.cs | 75 ++ .../BaseConfigurationService.cs} | 21 +- .../ConfigurationService.cs | 140 --- .../IConfigurationService.cs | 29 +- .../SessionManagement/SessionService.cs | 871 +++++++++--------- .../BaseStringTableService.cs | 100 ++ .../StringTableService/IStringTableService.cs | 55 ++ .../TopMenuEntry/ApplicationMenu.razor.cs | 6 +- .../Shared/TopMenuEntry/ModelMenu.razor.cs | 6 +- .../ViewModels/Components/ILoginViewModel.cs | 6 +- .../ViewModels/Components/LoginViewModel.cs | 8 +- .../Components/OpenModelViewModel.cs | 423 +++++---- .../ConfigurationService.cs} | 83 +- .../StringTableService/StringTableService.cs | 85 ++ COMET.Web.Common/_Imports.razor | 1 - .../ModelDashboardTestFixture.cs | 11 +- .../ParameterEditorTestFixture.cs | 7 +- .../Pages/Viewer/ViewerTestFixture.cs | 23 +- COMETwebapp.sln.DotSettings | 2 +- COMETwebapp/Program.cs | 19 +- 44 files changed, 1594 insertions(+), 1155 deletions(-) create mode 100644 COMET.Web.Common.Tests/Data/DefaultTextConfiguration.json create mode 100644 COMET.Web.Common.Tests/Resources/configuration/DefaultTextConfiguration.json create mode 100644 COMET.Web.Common.Tests/Server/Services/ConfigurationService/ConfigurationServiceTestFixture.cs create mode 100644 COMET.Web.Common.Tests/Server/Services/StringTableService/StringTableServiceTestFixture.cs create mode 100644 COMET.Web.Common/Extensions/ServiceCollectionExtensions.cs rename COMET.Web.Common/Extensions/{WebAssemblyHostExtensions.cs => ServiceProviderExtensions.cs} (61%) delete mode 100644 COMET.Web.Common/Extensions/WebAssemblyHostBuilderExtensions.cs create mode 100644 COMET.Web.Common/Server/Services/ConfigurationService/ConfigurationService.cs create mode 100644 COMET.Web.Common/Server/Services/StringTableService/StringTableService.cs rename COMET.Web.Common/Services/{ServerConnectionService/IServerConnectionService.cs => ConfigurationService/BaseConfigurationService.cs} (68%) delete mode 100644 COMET.Web.Common/Services/ConfigurationService/ConfigurationService.cs create mode 100644 COMET.Web.Common/Services/StringTableService/BaseStringTableService.cs create mode 100644 COMET.Web.Common/Services/StringTableService/IStringTableService.cs rename COMET.Web.Common/{Services/ServerConnectionService/ServerConnectionService.cs => WebAssembly/Services/ConfigurationService/ConfigurationService.cs} (51%) create mode 100644 COMET.Web.Common/WebAssembly/Services/StringTableService/StringTableService.cs diff --git a/COMET.Web.Common.Tests/COMET.Web.Common.Tests.csproj b/COMET.Web.Common.Tests/COMET.Web.Common.Tests.csproj index ae5312d8..c009ca19 100644 --- a/COMET.Web.Common.Tests/COMET.Web.Common.Tests.csproj +++ b/COMET.Web.Common.Tests/COMET.Web.Common.Tests.csproj @@ -13,6 +13,24 @@ false + + + + + + + + Always + true + PreserveNewest + + + Always + true + PreserveNewest + + + @@ -35,4 +53,9 @@ + + + + + diff --git a/COMET.Web.Common.Tests/Components/DashboardTestFixture.cs b/COMET.Web.Common.Tests/Components/DashboardTestFixture.cs index ce929962..9fcafd8e 100644 --- a/COMET.Web.Common.Tests/Components/DashboardTestFixture.cs +++ b/COMET.Web.Common.Tests/Components/DashboardTestFixture.cs @@ -34,8 +34,8 @@ namespace COMET.Web.Common.Tests.Components using COMET.Web.Common.Components; using COMET.Web.Common.Enumerations; using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.RegistrationService; + using COMET.Web.Common.Services.StringTableService; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; @@ -51,7 +51,7 @@ public class DashboardTestFixture { private List applications; private Mock registrationService; - private Mock configurationService; + private Mock configurationService; private TestContext context; [SetUp] @@ -83,7 +83,7 @@ public void Setup() this.registrationService.Setup(x => x.RegisteredApplications) .Returns(this.applications); - this.configurationService = new Mock(); + this.configurationService = new Mock(); this.configurationService.Setup(x => x.GetText(TextConfigurationKind.LandingPageTitle)).Returns(string.Empty); this.context = new TestContext(); diff --git a/COMET.Web.Common.Tests/Components/IndexComponentTestFixture.cs b/COMET.Web.Common.Tests/Components/IndexComponentTestFixture.cs index cbb384e2..60d7bfc8 100644 --- a/COMET.Web.Common.Tests/Components/IndexComponentTestFixture.cs +++ b/COMET.Web.Common.Tests/Components/IndexComponentTestFixture.cs @@ -40,8 +40,8 @@ namespace COMET.Web.Common.Tests.Components using COMET.Web.Common.Model; using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.RegistrationService; - using COMET.Web.Common.Services.ServerConnectionService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Services.VersionService; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.Utilities; @@ -67,7 +67,7 @@ public void Setup() this.context = new TestContext(); this.versionService = new Mock(); this.sessionService = new Mock(); - this.serverConnectionService = new Mock(); + this.serverConnectionService = new Mock(); this.sourceList = new SourceList(); this.sessionService.Setup(x => x.OpenIterations).Returns(this.sourceList); @@ -88,7 +88,7 @@ public void Setup() this.context.ConfigureDevExpressBlazor(); this.authorization = this.context.AddTestAuthorization(); - var configurationService = new Mock(); + var configurationService = new Mock(); configurationService.Setup(x => x.GetText(It.IsAny())).Returns("something"); this.context.Services.AddSingleton(configurationService.Object); } @@ -103,7 +103,7 @@ public void Teardown() private TestContext context; private Mock versionService; private Mock sessionService; - private Mock serverConnectionService; + private Mock serverConnectionService; private Mock authenticationService; private TestAuthorizationContext authorization; private SourceList sourceList; diff --git a/COMET.Web.Common.Tests/Components/LoginTestFixture.cs b/COMET.Web.Common.Tests/Components/LoginTestFixture.cs index fde5fdbd..95f84944 100644 --- a/COMET.Web.Common.Tests/Components/LoginTestFixture.cs +++ b/COMET.Web.Common.Tests/Components/LoginTestFixture.cs @@ -30,7 +30,7 @@ namespace COMET.Web.Common.Tests.Components using COMET.Web.Common.Components; using COMET.Web.Common.Enumerations; using COMET.Web.Common.Model.DTO; - using COMET.Web.Common.Services.ServerConnectionService; + using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.SessionManagement; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.ViewModels.Components; @@ -50,13 +50,13 @@ public class LoginTestFixture private ILoginViewModel viewModel; private TestContext context; private Mock authenticationService; - private Mock serverConnectionService; + private Mock serverConnectionService; [SetUp] public void Setup() { this.authenticationService = new Mock(); - this.serverConnectionService = new Mock(); + this.serverConnectionService = new Mock(); this.serverConnectionService.Setup(x => x.ServerAddress).Returns("http://localhost.com"); this.context = new TestContext(); this.viewModel = new LoginViewModel(this.authenticationService.Object, this.serverConnectionService.Object); diff --git a/COMET.Web.Common.Tests/Components/OpenModelTestFixture.cs b/COMET.Web.Common.Tests/Components/OpenModelTestFixture.cs index d12d6376..ecc32812 100644 --- a/COMET.Web.Common.Tests/Components/OpenModelTestFixture.cs +++ b/COMET.Web.Common.Tests/Components/OpenModelTestFixture.cs @@ -31,8 +31,8 @@ namespace COMET.Web.Common.Tests.Components using CDP4Common.SiteDirectoryData; using COMET.Web.Common.Components; - using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.ViewModels.Components; @@ -65,7 +65,7 @@ public void Setup() this.context.ConfigureDevExpressBlazor(); this.context.Services.AddSingleton(this.viewModel); - var configurationService = new Mock(); + var configurationService = new Mock(); this.context.Services.AddSingleton(configurationService.Object); } diff --git a/COMET.Web.Common.Tests/Components/SingleIterationApplicationTemplateTestFixture.cs b/COMET.Web.Common.Tests/Components/SingleIterationApplicationTemplateTestFixture.cs index 5a100f52..6da7ebfd 100644 --- a/COMET.Web.Common.Tests/Components/SingleIterationApplicationTemplateTestFixture.cs +++ b/COMET.Web.Common.Tests/Components/SingleIterationApplicationTemplateTestFixture.cs @@ -37,8 +37,8 @@ namespace COMET.Web.Common.Tests.Components using COMET.Web.Common.Components.Selectors; using COMET.Web.Common.Extensions; using COMET.Web.Common.Services.ConfigurationService; - using COMET.Web.Common.Services.ServerConnectionService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.ViewModels.Components; using COMET.Web.Common.ViewModels.Components.Selectors; @@ -76,8 +76,8 @@ public void Setup() this.viewModel.Setup(x => x.SessionService).Returns(sessionService.Object); this.context.Services.AddSingleton(this.viewModel.Object); this.context.Services.AddSingleton(); - this.context.Services.AddSingleton(); this.context.Services.AddSingleton(new Mock().Object); + this.context.Services.AddSingleton(new Mock().Object); this.context.Services.AddSingleton(sessionService.Object); this.context.ConfigureDevExpressBlazor(); } diff --git a/COMET.Web.Common.Tests/Data/DefaultTextConfiguration.json b/COMET.Web.Common.Tests/Data/DefaultTextConfiguration.json new file mode 100644 index 00000000..4b39342b --- /dev/null +++ b/COMET.Web.Common.Tests/Data/DefaultTextConfiguration.json @@ -0,0 +1,12 @@ +{ + "OpenEngineeringModelPlaceholder": "Select an Engineering Model", + "OpenIterationPlaceholder": "Select an Iteration", + "OpenDomainOfExpertisePlaceholder": "Select a Domain of Expertise", + "ModelTitleCaption": "Model", + "IterationTitleCaption": "Iteration", + "DomainTitleCaption": "Domain", + "LandingPageTitle": "", + "NavigationApplicationSelectorTitle": "Application", + "NavigationModelSelectorTitle": "Models", + "ModelOpenButtonCaption": "Open Model" +} diff --git a/COMET.Web.Common.Tests/Resources/configuration/DefaultTextConfiguration.json b/COMET.Web.Common.Tests/Resources/configuration/DefaultTextConfiguration.json new file mode 100644 index 00000000..4b39342b --- /dev/null +++ b/COMET.Web.Common.Tests/Resources/configuration/DefaultTextConfiguration.json @@ -0,0 +1,12 @@ +{ + "OpenEngineeringModelPlaceholder": "Select an Engineering Model", + "OpenIterationPlaceholder": "Select an Iteration", + "OpenDomainOfExpertisePlaceholder": "Select a Domain of Expertise", + "ModelTitleCaption": "Model", + "IterationTitleCaption": "Iteration", + "DomainTitleCaption": "Domain", + "LandingPageTitle": "", + "NavigationApplicationSelectorTitle": "Application", + "NavigationModelSelectorTitle": "Models", + "ModelOpenButtonCaption": "Open Model" +} diff --git a/COMET.Web.Common.Tests/Server/Services/ConfigurationService/ConfigurationServiceTestFixture.cs b/COMET.Web.Common.Tests/Server/Services/ConfigurationService/ConfigurationServiceTestFixture.cs new file mode 100644 index 00000000..405bf5c1 --- /dev/null +++ b/COMET.Web.Common.Tests/Server/Services/ConfigurationService/ConfigurationServiceTestFixture.cs @@ -0,0 +1,74 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Tests.Server.Services.ConfigurationService +{ + using COMET.Web.Common.Server.Services.ConfigurationService; + + using Microsoft.Extensions.Configuration; + + using Moq; + + using NUnit.Framework; + + [TestFixture] + public class ConfigurationServiceTestFixture + { + [Test] + public async Task VerifyInitializeServiceWithEmptyConfiguration() + { + var configuration = new Mock(); + configuration.Setup(x => x.GetSection(ConfigurationService.AddressSection)).Returns(new Mock().Object); + var service = new ConfigurationService(configuration.Object); + await service.InitializeService(); + + Assert.Multiple(() => + { + configuration.Verify(x => x.GetSection(ConfigurationService.AddressSection), Times.Once); + Assert.That(service.ServerAddress, Is.Null); + }); + + await service.InitializeService(); + configuration.Verify(x => x.GetSection(ConfigurationService.AddressSection), Times.Once); + } + + [Test] + public async Task VerifyInitializeServiceWithConfiguration() + { + var configurationSection = new Mock(); + configurationSection.Setup(x => x.Value).Returns("https://a.b.c"); + var configuration = new Mock(); + configuration.Setup(x => x.GetSection(ConfigurationService.AddressSection)).Returns(configurationSection.Object); + var service = new ConfigurationService(configuration.Object); + await service.InitializeService(); + + Assert.Multiple(() => + { + configuration.Verify(x => x.GetSection(ConfigurationService.AddressSection), Times.Once); + Assert.That(service.ServerAddress, Is.EqualTo(configurationSection.Object.Value)); + }); + } + } +} diff --git a/COMET.Web.Common.Tests/Server/Services/StringTableService/StringTableServiceTestFixture.cs b/COMET.Web.Common.Tests/Server/Services/StringTableService/StringTableServiceTestFixture.cs new file mode 100644 index 00000000..d24b7d22 --- /dev/null +++ b/COMET.Web.Common.Tests/Server/Services/StringTableService/StringTableServiceTestFixture.cs @@ -0,0 +1,58 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Tests.Server.Services.StringTableService +{ + using COMET.Web.Common.Enumerations; + using COMET.Web.Common.Server.Services.StringTableService; + + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Logging.Abstractions; + + using Moq; + + using NUnit.Framework; + + [TestFixture] + public class StringTableServiceTestFixture + { + [Test] + public async Task VerifyServiceInitialization() + { + var configuration = new Mock(); + configuration.Setup(x => x["StringTablePath"]).Returns(""); + + var service = new StringTableService(configuration.Object, NullLogger.Instance); + await service.InitializeService(); + Assert.That(() => service.GetText(TextConfigurationKind.DomainTitleCaption), Throws.Exception); + + configuration.Setup(x => x["StringTablePath"]).Returns(Path.Combine("Resources", "configuration", "DefaultTextConfiguration.json")); + + service = new StringTableService(configuration.Object, NullLogger.Instance); + await service.InitializeService(); + Assert.That(() => service.GetText(TextConfigurationKind.DomainTitleCaption), Throws.Nothing); + } + } +} diff --git a/COMET.Web.Common.Tests/Services/ConfigurationService/ConfigurationServiceTestFixture.cs b/COMET.Web.Common.Tests/Services/ConfigurationService/ConfigurationServiceTestFixture.cs index c1cdfaa6..b5cffdba 100644 --- a/COMET.Web.Common.Tests/Services/ConfigurationService/ConfigurationServiceTestFixture.cs +++ b/COMET.Web.Common.Tests/Services/ConfigurationService/ConfigurationServiceTestFixture.cs @@ -1,4 +1,5 @@ -// -------------------------------------------------------------------------------------------------------------------- +/* +// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) 2023 RHEA System S.A. // @@ -22,13 +23,15 @@ // // // -------------------------------------------------------------------------------------------------------------------- + namespace COMET.Web.Common.Tests.Services.ConfigurationService { using System.Net; using COMET.Web.Common.Enumerations; using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; + using COMET.Web.Common.Services.StringTableService; + using COMET.Web.Common.WebAssembly.Services.StringTableService; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -41,7 +44,7 @@ namespace COMET.Web.Common.Tests.Services.ConfigurationService [TestFixture] public class ConfigurationServiceTestFixture { - private IConfigurationService configurationService; + private IStringTableService stringTableService; [Test] public async Task VerifyService() @@ -87,29 +90,29 @@ public async Task VerifyService() BaseAddress = new Uri("http://localhost") }; - var loggerMock = new Mock>(); - this.configurationService = new ConfigurationService(options.Object, httpClient, loggerMock.Object); + var loggerMock = new Mock>(); + this.stringTableService = new StringTableService(options.Object, httpClient, loggerMock.Object); Assert.Multiple(() => { - Assert.That(this.configurationService, Is.Not.Null); - Assert.Throws(()=>this.configurationService.GetText("")); + Assert.That(this.stringTableService, Is.Not.Null); + Assert.Throws(()=>this.stringTableService.GetText("")); }); - await this.configurationService.InitializeService(); + await this.stringTableService.InitializeService(); Assert.Multiple(() => { - Assert.DoesNotThrow(() => this.configurationService.GetText("")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.OpenEngineeringModelPlaceholder), Is.EqualTo("Select an Engineering Model")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.OpenIterationPlaceholder), Is.EqualTo("Select an Iteration")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.OpenDomainOfExpertisePlaceholder), Is.EqualTo("Select a Domain of Expertise")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.ModelTitleCaption), Is.EqualTo("Model")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.IterationTitleCaption), Is.EqualTo("Iteration")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.DomainTitleCaption), Is.EqualTo("Domain")); - Assert.That(this.configurationService.GetText(TextConfigurationKind.LandingPageTitle), Is.EqualTo("")); - Assert.That(this.configurationService.GetConfigurations(), Is.Not.Null); - Assert.That(this.configurationService.GetConfigurations(), Is.Not.Empty); + Assert.DoesNotThrow(() => this.stringTableService.GetText("")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.OpenEngineeringModelPlaceholder), Is.EqualTo("Select an Engineering Model")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.OpenIterationPlaceholder), Is.EqualTo("Select an Iteration")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.OpenDomainOfExpertisePlaceholder), Is.EqualTo("Select a Domain of Expertise")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.ModelTitleCaption), Is.EqualTo("Model")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.IterationTitleCaption), Is.EqualTo("Iteration")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.DomainTitleCaption), Is.EqualTo("Domain")); + Assert.That(this.stringTableService.GetText(TextConfigurationKind.LandingPageTitle), Is.EqualTo("")); + Assert.That(this.stringTableService.GetConfigurations(), Is.Not.Null); + Assert.That(this.stringTableService.GetConfigurations(), Is.Not.Empty); }); } @@ -157,16 +160,17 @@ public async Task VerifyExceptionIsNotThrown() BaseAddress = new Uri("http://localhost") }; - var loggerMock = new Mock>(); - this.configurationService = new ConfigurationService(options.Object, httpClient, loggerMock.Object); + var loggerMock = new Mock>(); + this.stringTableService = new StringTableService(options.Object, httpClient, loggerMock.Object); - await this.configurationService.InitializeService(); + await this.stringTableService.InitializeService(); Assert.Multiple(() => { - Assert.That(this.configurationService.GetConfigurations(), Is.Not.Null); - Assert.That(this.configurationService.GetConfigurations(), Is.Empty); + Assert.That(this.stringTableService.GetConfigurations(), Is.Not.Null); + Assert.That(this.stringTableService.GetConfigurations(), Is.Empty); }); } } } +*/ diff --git a/COMET.Web.Common.Tests/Services/ServerConnectionService/ServerConnectionServiceTestFixture.cs b/COMET.Web.Common.Tests/Services/ServerConnectionService/ServerConnectionServiceTestFixture.cs index 9ad28715..00a3c80e 100644 --- a/COMET.Web.Common.Tests/Services/ServerConnectionService/ServerConnectionServiceTestFixture.cs +++ b/COMET.Web.Common.Tests/Services/ServerConnectionService/ServerConnectionServiceTestFixture.cs @@ -1,4 +1,5 @@ -// -------------------------------------------------------------------------------------------------------------------- +/* +// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) 2023 RHEA System S.A. // @@ -27,7 +28,7 @@ namespace COMET.Web.Common.Tests.Services.ServerConnectionService using System.Net; using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ServerConnectionService; + using COMET.Web.Common.Services.ConfigurationService; using Microsoft.Extensions.Options; @@ -39,7 +40,7 @@ namespace COMET.Web.Common.Tests.Services.ServerConnectionService [TestFixture] public class ServerConnectionServiceTestFixture { - private IServerConnectionService serverConnectionService; + private IConfigurationService serverConnectionService; [Test] public async Task VerifyService() @@ -141,3 +142,4 @@ public async Task VerifyService() } } } +*/ diff --git a/COMET.Web.Common.Tests/Shared/TopMenuTestFixture.cs b/COMET.Web.Common.Tests/Shared/TopMenuTestFixture.cs index 75cbb266..2408d0b9 100644 --- a/COMET.Web.Common.Tests/Shared/TopMenuTestFixture.cs +++ b/COMET.Web.Common.Tests/Shared/TopMenuTestFixture.cs @@ -38,10 +38,10 @@ namespace COMET.Web.Common.Tests.Shared using COMET.Web.Common.Components; using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.NotificationService; using COMET.Web.Common.Services.RegistrationService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Services.VersionService; using COMET.Web.Common.Shared; using COMET.Web.Common.Shared.TopMenuEntry; @@ -72,7 +72,7 @@ public class TopMenuTestFixture private Mock authenticationService; private Mock registrationService; private Mock versionService; - private Mock configurationService; + private Mock configurationService; private SourceList sourceList; private List registeredMenuEntries; private List registeredApplications; @@ -105,7 +105,7 @@ public void Setup() this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); - this.configurationService = new Mock(); + this.configurationService = new Mock(); this.context.Services.AddSingleton(this.configurationService.Object); this.context.ConfigureDevExpressBlazor(); } diff --git a/COMET.Web.Common/COMET.Web.Common.csproj b/COMET.Web.Common/COMET.Web.Common.csproj index 5d7d66a5..e883ffc5 100644 --- a/COMET.Web.Common/COMET.Web.Common.csproj +++ b/COMET.Web.Common/COMET.Web.Common.csproj @@ -30,8 +30,8 @@ - + diff --git a/COMET.Web.Common/Components/Dashboard.razor.cs b/COMET.Web.Common/Components/Dashboard.razor.cs index 00bb7c61..497dcd3a 100644 --- a/COMET.Web.Common/Components/Dashboard.razor.cs +++ b/COMET.Web.Common/Components/Dashboard.razor.cs @@ -26,8 +26,8 @@ namespace COMET.Web.Common.Components { using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.RegistrationService; + using COMET.Web.Common.Services.StringTableService; using Microsoft.AspNetCore.Components; @@ -43,9 +43,9 @@ public partial class Dashboard internal IRegistrationService RegistrationService { get; set; } /// - /// The + /// The /// [Inject] - public IConfigurationService ConfigurationService { get; set; } + public IStringTableService ConfigurationService { get; set; } } } diff --git a/COMET.Web.Common/Components/Login.razor.cs b/COMET.Web.Common/Components/Login.razor.cs index 9e251cb0..2520c56c 100644 --- a/COMET.Web.Common/Components/Login.razor.cs +++ b/COMET.Web.Common/Components/Login.razor.cs @@ -26,7 +26,6 @@ namespace COMET.Web.Common.Components { using COMET.Web.Common.Enumerations; - using COMET.Web.Common.Services.ServerConnectionService; using COMET.Web.Common.ViewModels.Components; using Microsoft.AspNetCore.Components; diff --git a/COMET.Web.Common/Components/OpenModel.razor.cs b/COMET.Web.Common/Components/OpenModel.razor.cs index d989f283..24ffbab1 100644 --- a/COMET.Web.Common/Components/OpenModel.razor.cs +++ b/COMET.Web.Common/Components/OpenModel.razor.cs @@ -28,7 +28,7 @@ namespace COMET.Web.Common.Components using CDP4Common.EngineeringModelData; using CDP4Common.SiteDirectoryData; - using COMET.Web.Common.Services.ConfigurationService; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.ViewModels.Components; using Microsoft.AspNetCore.Components; @@ -41,10 +41,10 @@ namespace COMET.Web.Common.Components public partial class OpenModel { /// - /// Gets or sets the + /// Gets or sets the /// [Inject] - public IConfigurationService ConfigurationService { get; set; } + public IStringTableService ConfigurationService { get; set; } /// /// Value asserting that selectors for and are enabled diff --git a/COMET.Web.Common/Components/ParameterTypeEditors/DateTimeParameterTypeEditor.razor b/COMET.Web.Common/Components/ParameterTypeEditors/DateTimeParameterTypeEditor.razor index b13eb7d2..d7296a60 100644 --- a/COMET.Web.Common/Components/ParameterTypeEditors/DateTimeParameterTypeEditor.razor +++ b/COMET.Web.Common/Components/ParameterTypeEditors/DateTimeParameterTypeEditor.razor @@ -25,17 +25,24 @@ @{ var dateTimeStringSplitted = this.ViewModel.ValueArray[this.ViewModel.ValueArrayIndex].Split('T'); - DateTime.TryParse(dateTimeStringSplitted[0], out var dateTime); + var timeSpan = TimeSpan.Zero; - var timeString = dateTimeStringSplitted[1]; - var values = timeString.Split(':'); + if (!DateTime.TryParse(dateTimeStringSplitted[0], out var dateTime)) + { + dateTime = default; + } + else + { + var timeString = dateTimeStringSplitted[1]; + var values = timeString.Split(':'); - int.TryParse(values[0], out var hours); - int.TryParse(values[1], out var minutes); - int.TryParse(values[2], out var seconds); + int.TryParse(values[0], out var hours); + int.TryParse(values[1], out var minutes); + int.TryParse(values[2], out var seconds); + + timeSpan = new TimeSpan(hours, minutes, seconds); + } - var timeSpan = new TimeSpan(hours, minutes, seconds); - - /// The + /// The /// [Inject] - public IServerConnectionService ServerConnectionService { get; set; } + public IConfigurationService ServerConnectionService { get; set; } /// /// Method invoked when the component is ready to start, having received its diff --git a/COMET.Web.Common/Components/ValueSetRenderers/ValueArrayDetails.razor b/COMET.Web.Common/Components/ValueSetRenderers/ValueArrayDetails.razor index ed843491..2e6e154f 100644 --- a/COMET.Web.Common/Components/ValueSetRenderers/ValueArrayDetails.razor +++ b/COMET.Web.Common/Components/ValueSetRenderers/ValueArrayDetails.razor @@ -28,28 +28,34 @@ Value="@(this.Value.First())" Scale="@(this.Scale)"/> } -else if (this.ParameterType is ArrayParameterType arrayParameterType) -{ - -} else -{ - var compoundParameterType = (CompoundParameterType)this.ParameterType; -
- @foreach (var component in compoundParameterType.Component.ToList()) + switch (this.ParameterType) + { + case ArrayParameterType arrayParameterType: + + break; + case CompoundParameterType compoundParameterType: { - var indexStart = 0; - for (var componentIndex = 0; componentIndex < compoundParameterType.Component.IndexOf(component); componentIndex++) - { - indexStart += compoundParameterType.Component.ElementAt(componentIndex).ParameterType.NumberOfValues; - } +
+ @foreach (var component in compoundParameterType.Component.ToList()) + { + var indexStart = 0; + for (var componentIndex = 0; componentIndex < compoundParameterType.Component.IndexOf(component); componentIndex++) + { + indexStart += compoundParameterType.Component.ElementAt(componentIndex).ParameterType.NumberOfValues; + } - + + } +
+ break; } -
-} \ No newline at end of file + case SampledFunctionParameterType sfpt: +
Component under development
+ break; + } \ No newline at end of file diff --git a/COMET.Web.Common/Extensions/ServiceCollectionExtensions.cs b/COMET.Web.Common/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..3d9bb1b1 --- /dev/null +++ b/COMET.Web.Common/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,105 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Extensions +{ + using COMET.Web.Common.Model; + using COMET.Web.Common.Server.Services.ConfigurationService; + using COMET.Web.Common.Server.Services.StringTableService; + using COMET.Web.Common.Services.ConfigurationService; + using COMET.Web.Common.Services.NotificationService; + using COMET.Web.Common.Services.RegistrationService; + using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; + using COMET.Web.Common.Services.VersionService; + using COMET.Web.Common.ViewModels.Components; + using COMET.Web.Common.ViewModels.Components.Publications; + using COMET.Web.Common.ViewModels.Components.Selectors; + using COMET.Web.Common.ViewModels.Shared.TopMenuEntry; + + using DevExpress.Blazor; + + using Microsoft.AspNetCore.Components.Authorization; + using Microsoft.Extensions.DependencyInjection; + + /// + /// Extension class for + /// + public static class ServiceCollectionExtensions + { + /// + /// Register required Services + /// + /// The + /// Value asserting if the application is a Blazor Server application + /// The optional + public static void RegisterCommonLibrary(this IServiceCollection serviceProvider, bool isBlazorServer = true, Action globalOptions = null) + { + if (isBlazorServer) + { + serviceProvider.AddSingleton(); + serviceProvider.AddSingleton(); + } + else + { + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + } + + if (globalOptions != null) + { + serviceProvider.Configure(globalOptions); + } + + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + serviceProvider.AddSingleton(); + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + serviceProvider.AddAuthorizationCore(); + serviceProvider.AddDevExpressBlazor(configure => configure.SizeMode = SizeMode.Medium); + serviceProvider.RegisterCommonViewModels(); + } + + /// + /// Register required View Models + /// + /// The + private static void RegisterCommonViewModels(this IServiceCollection serviceProvider) + { + serviceProvider.AddTransient(); + serviceProvider.AddTransient(); + serviceProvider.AddTransient(); + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + serviceProvider.AddScoped(); + serviceProvider.AddTransient(); + serviceProvider.AddTransient(); + serviceProvider.AddTransient(); + } + } +} diff --git a/COMET.Web.Common/Extensions/WebAssemblyHostExtensions.cs b/COMET.Web.Common/Extensions/ServiceProviderExtensions.cs similarity index 61% rename from COMET.Web.Common/Extensions/WebAssemblyHostExtensions.cs rename to COMET.Web.Common/Extensions/ServiceProviderExtensions.cs index fe52ca1c..d262fc1b 100644 --- a/COMET.Web.Common/Extensions/WebAssemblyHostExtensions.cs +++ b/COMET.Web.Common/Extensions/ServiceProviderExtensions.cs @@ -1,59 +1,60 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023 RHEA System S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar -// -// This file is part of COMET WEB Community Edition -// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 -// Annex A and Annex C. -// -// 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. -// -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace COMET.Web.Common.Extensions -{ - using COMET.Web.Common.Services.ConfigurationService; - using COMET.Web.Common.Services.ServerConnectionService; - - using Microsoft.AspNetCore.Components.WebAssembly.Hosting; - - /// - /// Class for extensions methods for - /// - public static class WebAssemblyHostExtensions - { - /// - /// Initialize the neccesary services of the webapp - /// - /// the - /// an asynchronous operation - public static async Task InitializeServices(this WebAssemblyHost host) - { - var service = host.Services.GetService(typeof(IConfigurationService)); - var serverConnectionService = host.Services.GetService(typeof(IServerConnectionService)); - - if (service is ConfigurationService configurationService) - { - await configurationService.InitializeService(); - } - - if (serverConnectionService is ServerConnectionService serverConfigurationService) - { - await serverConfigurationService.InitializeService(); - } - } - } -} +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Extensions +{ + using COMET.Web.Common.Services.ConfigurationService; + using COMET.Web.Common.Services.StringTableService; + + using Microsoft.Extensions.DependencyInjection; + + /// + /// Extension class for + /// + public static class ServiceProviderExtensions + { + /// + /// Initialize the neccesary services of the webapp + /// + /// the + /// an asynchronous operation + public static async Task InitializeServices(this IServiceProvider serviceProvider) + { + var stringTableService = serviceProvider.GetRequiredService(); + + if (stringTableService != null) + { + await stringTableService.InitializeService(); + } + + var configurationService = serviceProvider.GetRequiredService(); + + if (configurationService != null) + { + await configurationService.InitializeService(); + } + } + } +} diff --git a/COMET.Web.Common/Extensions/WebAssemblyHostBuilderExtensions.cs b/COMET.Web.Common/Extensions/WebAssemblyHostBuilderExtensions.cs deleted file mode 100644 index a6d0b292..00000000 --- a/COMET.Web.Common/Extensions/WebAssemblyHostBuilderExtensions.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023 RHEA System S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar -// -// This file is part of COMET WEB Community Edition -// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 -// Annex A and Annex C. -// -// 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. -// -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace COMET.Web.Common.Extensions -{ - using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; - using COMET.Web.Common.Services.NotificationService; - using COMET.Web.Common.Services.RegistrationService; - using COMET.Web.Common.Services.ServerConnectionService; - using COMET.Web.Common.Services.SessionManagement; - using COMET.Web.Common.Services.VersionService; - using COMET.Web.Common.ViewModels.Components; - using COMET.Web.Common.ViewModels.Components.Publications; - using COMET.Web.Common.ViewModels.Components.Selectors; - using COMET.Web.Common.ViewModels.Shared.TopMenuEntry; - - using DevExpress.Blazor; - - using Microsoft.AspNetCore.Components.Authorization; - using Microsoft.AspNetCore.Components.Web; - using Microsoft.AspNetCore.Components.WebAssembly.Hosting; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - - /// - /// Extensions for the - /// - public static class WebAssemblyHostBuilderExtensions - { - /// - /// Add all required Services and ViewModels for this Library inside the - /// - /// The - /// An to configure this library - public static void AddCometWebCommon(this WebAssemblyHostBuilder builder, Action options = null) - { - builder.RootComponents.Add("#app"); - builder.RootComponents.Add("head::after"); - - if (options != null) - { - builder.Services.Configure(options); - } - - builder.Services.AddAuthorizationCore(); - builder.Services.AddScoped(_ => new HttpClient() - { - BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) - }); - - builder.RegisterServices(); - builder.RegisterViewModels(); - builder.Services.AddDevExpressBlazor(configure => configure.SizeMode = SizeMode.Medium); - } - - /// - /// Register required Services - /// - /// The - private static void RegisterServices(this WebAssemblyHostBuilder builder) - { - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - } - - /// - /// Register required View Models - /// - /// The - private static void RegisterViewModels(this WebAssemblyHostBuilder builder) - { - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - } - } -} diff --git a/COMET.Web.Common/Server/Services/ConfigurationService/ConfigurationService.cs b/COMET.Web.Common/Server/Services/ConfigurationService/ConfigurationService.cs new file mode 100644 index 00000000..cff351c5 --- /dev/null +++ b/COMET.Web.Common/Server/Services/ConfigurationService/ConfigurationService.cs @@ -0,0 +1,78 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Server.Services.ConfigurationService +{ + using COMET.Web.Common.Services.ConfigurationService; + + using Microsoft.Extensions.Configuration; + + /// + /// Service that holds the configuration for the application + /// + public class ConfigurationService : BaseConfigurationService + { + /// + /// Gets the ServerAddress section key + /// + public const string AddressSection = "ServerAddress"; + + /// + /// Gets the + /// + private readonly IConfiguration configuration; + + /// + /// Initializes a new instance of + /// + /// The + public ConfigurationService(IConfiguration configuration) + { + this.configuration = configuration; + } + + /// + /// Initializes the + /// + /// an asynchronous operation + public override Task InitializeService() + { + if (this.IsInitialized) + { + return Task.CompletedTask; + } + + var addressSection = this.configuration.GetSection(AddressSection); + + if (addressSection.Exists()) + { + this.ServerAddress = addressSection.Value; + } + + this.IsInitialized = true; + return Task.CompletedTask; + } + } +} diff --git a/COMET.Web.Common/Server/Services/StringTableService/StringTableService.cs b/COMET.Web.Common/Server/Services/StringTableService/StringTableService.cs new file mode 100644 index 00000000..c00b32bc --- /dev/null +++ b/COMET.Web.Common/Server/Services/StringTableService/StringTableService.cs @@ -0,0 +1,75 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Server.Services.StringTableService +{ + using System.Text.Json; + + using COMET.Web.Common.Services.StringTableService; + + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Logging; + + /// + /// Service implementation that holds the text data from the configuration file + /// + public class StringTableService : BaseStringTableService + { + /// + /// Initializes a new instance of the class. + /// + /// The + /// The + public StringTableService(IConfiguration configuration, ILogger logger) : base(logger) + { + this.FilePath = configuration["StringTablePath"]; + } + + /// + /// Initializes the + /// + /// an asynchronous operation + public override async Task InitializeService() + { + if (this.IsInitialized) + { + return; + } + + try + { + var jsonContent = await File.ReadAllTextAsync(this.FilePath); + this.Configurations = JsonSerializer.Deserialize>(jsonContent); + } + catch (Exception e) + { + this.Logger.LogError(e, "Error while getting the configuration file."); + return; + } + + this.IsInitialized = true; + } + } +} diff --git a/COMET.Web.Common/Services/ServerConnectionService/IServerConnectionService.cs b/COMET.Web.Common/Services/ConfigurationService/BaseConfigurationService.cs similarity index 68% rename from COMET.Web.Common/Services/ServerConnectionService/IServerConnectionService.cs rename to COMET.Web.Common/Services/ConfigurationService/BaseConfigurationService.cs index bc0e2949..c9f7e177 100644 --- a/COMET.Web.Common/Services/ServerConnectionService/IServerConnectionService.cs +++ b/COMET.Web.Common/Services/ConfigurationService/BaseConfigurationService.cs @@ -1,8 +1,8 @@ // -------------------------------------------------------------------------------------------------------------------- -// +// // Copyright (c) 2023 RHEA System S.A. // -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine // // This file is part of COMET WEB Community Edition // The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 @@ -23,22 +23,27 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace COMET.Web.Common.Services.ServerConnectionService +namespace COMET.Web.Common.Services.ConfigurationService { /// - /// Service that holds the text data from the configuration file + /// Base Service that holds the configuration for the application /// - public interface IServerConnectionService + public abstract class BaseConfigurationService: IConfigurationService { + /// + /// Value to assert that the service has been initialized + /// + protected bool IsInitialized { get; set; } + /// /// The Server Address to use /// - string ServerAddress { get; } + public string ServerAddress { get; protected set; } /// - /// Initializes the + /// Initializes the /// /// an asynchronous operation - Task InitializeService(); + public abstract Task InitializeService(); } } diff --git a/COMET.Web.Common/Services/ConfigurationService/ConfigurationService.cs b/COMET.Web.Common/Services/ConfigurationService/ConfigurationService.cs deleted file mode 100644 index d7361189..00000000 --- a/COMET.Web.Common/Services/ConfigurationService/ConfigurationService.cs +++ /dev/null @@ -1,140 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023 RHEA System S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar -// -// This file is part of COMET WEB Community Edition -// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 -// Annex A and Annex C. -// -// 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. -// -// -// -------------------------------------------------------------------------------------------------------------------- -namespace COMET.Web.Common.Services.ConfigurationService -{ - using System.Text.Json; - - using COMET.Web.Common.Enumerations; - using COMET.Web.Common.Model; - using COMET.Web.Common.Utilities; - - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - - /// - /// Service that holds the text data from the configuration file - /// - public class ConfigurationService : IConfigurationService - { - /// - /// The json file that contains the configuration - /// - private readonly string jsonFile; - - /// - /// The used to retrieve the json - /// - private readonly HttpClient http; - - /// - /// The - /// - private readonly ILogger logger; - - /// - /// The dictionary that contains the map between the configuration and the value - /// - private Dictionary configurations = new(); - - /// - /// Value to assert that the service has been initialized - /// - private bool isInitialized; - - /// - /// Creates a new instance of type - /// - /// the - /// the - /// the - public ConfigurationService(IOptions options, HttpClient httpClient, ILogger logger) - { - this.jsonFile = options.Value.JsonConfigurationFile ?? "DefaultTextConfiguration.json"; - this.http = httpClient; - this.logger = logger; - } - - /// - /// Initializes the - /// - /// an asynchronous operation - public async Task InitializeService() - { - if (this.isInitialized) - { - return; - } - - try - { - var path = ContentPathBuilder.BuildPath(this.jsonFile); - var jsonContent = await this.http.GetStreamAsync(path); - this.configurations = JsonSerializer.Deserialize>(jsonContent); - } - catch (Exception e) - { - this.logger.LogError(e, "Error while getting the configuration file."); - return; - } - - this.isInitialized = true; - } - - /// - /// Gets the text asociated to a key - /// - /// the key - /// the text asociated to the key - public string GetText(string key) - { - if (!this.isInitialized) - { - throw new InvalidOperationException("The Service hasn't been initialized"); - } - - this.configurations.TryGetValue(key, out var value); - return value; - } - - /// - /// Gets the text asociated to a key - /// - /// the key - /// the text asociated to the key - public string GetText(TextConfigurationKind configurationKind) - { - return this.GetText(configurationKind.ToString()); - } - - /// - /// Gets the configurations of the - /// - /// a dictionary with the configurations - public Dictionary GetConfigurations() - { - return this.configurations; - } - } -} diff --git a/COMET.Web.Common/Services/ConfigurationService/IConfigurationService.cs b/COMET.Web.Common/Services/ConfigurationService/IConfigurationService.cs index 1dc66cd5..9ebc0a75 100644 --- a/COMET.Web.Common/Services/ConfigurationService/IConfigurationService.cs +++ b/COMET.Web.Common/Services/ConfigurationService/IConfigurationService.cs @@ -25,37 +25,20 @@ namespace COMET.Web.Common.Services.ConfigurationService { - using COMET.Web.Common.Enumerations; - /// - /// Service that holds the text data from the configuration file + /// Service that holds the configuration for the application /// public interface IConfigurationService { /// - /// Initializes the - /// - /// an asynchronous operation - Task InitializeService(); - - /// - /// Gets the text asociated to a key + /// The Server Address to use /// - /// the key - /// the text asociated to the key - string GetText(string key); + string ServerAddress { get; } /// - /// Gets the text asociated to a key - /// - /// the key - /// the text asociated to the key - string GetText(TextConfigurationKind configurationKind); - - /// - /// Gets the configurations of the + /// Initializes the /// - /// a dictionary with the configurations - Dictionary GetConfigurations(); + /// an asynchronous operation + Task InitializeService(); } } diff --git a/COMET.Web.Common/Services/SessionManagement/SessionService.cs b/COMET.Web.Common/Services/SessionManagement/SessionService.cs index e1cf864a..eb213819 100644 --- a/COMET.Web.Common/Services/SessionManagement/SessionService.cs +++ b/COMET.Web.Common/Services/SessionManagement/SessionService.cs @@ -1,437 +1,444 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023 RHEA System S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar -// -// This file is part of COMET WEB Community Edition -// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 -// Annex A and Annex C. -// -// 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. -// -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace COMET.Web.Common.Services.SessionManagement -{ - using System.Diagnostics; - - using CDP4Common.CommonData; - using CDP4Common.EngineeringModelData; - using CDP4Common.SiteDirectoryData; - - using CDP4Dal; - using CDP4Dal.Exceptions; - using CDP4Dal.Operations; - - using COMET.Web.Common.Enumerations; - - using DynamicData; - - using NLog; - - using ReactiveUI; - - /// - /// The purpose of the is to provide access to - /// an instance of - /// - public class SessionService : ReactiveObject, ISessionService - { - /// - /// The current class - /// - private readonly Logger logger = LogManager.GetCurrentClassLogger(); - - /// - /// Gets or sets the - /// - public ISession Session { get; set; } - - /// - /// A reactive collection of opened - /// - public SourceList OpenIterations { get; private set; } = new(); - - /// - /// True if the is opened - /// - public bool IsSessionOpen { get; set; } - - /// - /// Retrieves the that is loaded in the - /// - /// The - public SiteDirectory GetSiteDirectory() - { - return this.Session.RetrieveSiteDirectory(); - } - - /// - /// Close the ISession - /// - /// a - public async Task Close() - { - if (!this.IsSessionOpen) - { - return; - } - - await this.Session.Close(); - this.IsSessionOpen = false; - this.CloseIterations(); - } - - /// - /// Open the iteration with the selected and - /// - /// The selected - /// The - public async Task ReadIteration(IterationSetup iterationSetup, DomainOfExpertise domain) - { - var modelSetup = (EngineeringModelSetup)iterationSetup.Container; - var model = new EngineeringModel(modelSetup.EngineeringModelIid, this.Session.Assembler.Cache, this.Session.Credentials.Uri); - - var iteration = new Iteration(iterationSetup.IterationIid, this.Session.Assembler.Cache, this.Session.Credentials.Uri) - { - Container = model - }; - - try - { - await this.Session.Read(iteration, domain); - - if (this.Session.OpenIterations.All(x => x.Key.Iid != iterationSetup.IterationIid)) - { - throw new InvalidOperationException("The requested iteration could not be opened"); - } - - var openedIteration = this.Session.OpenIterations.FirstOrDefault(x => x.Key.Iid == iterationSetup.IterationIid).Key; - this.OpenIterations.Add(openedIteration); - - CDPMessageBus.Current.SendMessage(SessionStateKind.IterationOpened); - } - catch (Exception exception) - { - this.logger.Error($"During read operation an error has occured: {exception.Message}"); - throw; - } - } - - /// - /// Close all the opened - /// - public void CloseIterations() - { - foreach (var iteration in this.OpenIterations.Items.ToList()) - { - this.CloseIteration(iteration); - } - } - - /// - /// Closes an - /// - /// The - public void CloseIteration(Iteration iteration) - { - this.Session.CloseIterationSetup(iteration.IterationSetup); - this.OpenIterations.Remove(this.OpenIterations.Items.First(x => x.Iid == iteration.Iid)); - } - - /// - /// Get available for the ActivePerson - /// - /// - /// A container of - /// - public IEnumerable GetParticipantModels() - { - return this.GetSiteDirectory().Model - .Where(m => m.Participant.Any(p => p.Person.Name.Equals(this.Session.ActivePerson.Name))); - } - - /// - /// Get available for the active person in the selected - /// - /// - /// The selected - /// - /// A container of accessible for the active person - /// - public IEnumerable GetModelDomains(EngineeringModelSetup modelSetup) - { - var domains = new List(); - modelSetup?.Participant.FindAll(p => p.Person.Iid.Equals(this.Session.ActivePerson.Iid)).ForEach(p => p.Domain.ForEach(d => domains.Add(d))); - return domains.DistinctBy(d => d.Name).OrderBy(d => d.Name); - } - - /// - /// Refresh the ISession object - /// - public async Task RefreshSession() - { - var sw = Stopwatch.StartNew(); - CDPMessageBus.Current.SendMessage(SessionStateKind.Refreshing); - - await this.Session.Refresh(); - - Console.WriteLine($"Session refreshed in {sw.ElapsedMilliseconds} [ms]"); - } - - /// - /// Switches the current domain for an opened iteration - /// - /// The - /// The domain - public void SwitchDomain(Iteration iteration, DomainOfExpertise domainOfExpertise) - { - this.Session.SwitchDomain(iteration.Iid, domainOfExpertise); - } - - /// - /// Write a new Thing in an - /// - /// the container where the should be created - /// the thing to create in the session - /// An asynchronous operation - public async Task CreateThing(Thing container, Thing thingToCreate) - { - await this.CreateThings(container, new List { thingToCreate }); - } - +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Services.SessionManagement +{ + using System.Diagnostics; + + using CDP4Common.CommonData; + using CDP4Common.EngineeringModelData; + using CDP4Common.SiteDirectoryData; + + using CDP4Dal; + using CDP4Dal.Exceptions; + using CDP4Dal.Operations; + + using COMET.Web.Common.Enumerations; + + using DynamicData; + + using NLog; + + using ReactiveUI; + + /// + /// The purpose of the is to provide access to + /// an instance of + /// + public class SessionService : ReactiveObject, ISessionService + { + /// + /// The current class + /// + private readonly Logger logger = LogManager.GetCurrentClassLogger(); + + /// + /// Gets or sets the + /// + public ISession Session { get; set; } + + /// + /// A reactive collection of opened + /// + public SourceList OpenIterations { get; private set; } = new(); + + /// + /// True if the is opened + /// + public bool IsSessionOpen { get; set; } + + /// + /// Retrieves the that is loaded in the + /// + /// The + public SiteDirectory GetSiteDirectory() + { + return this.Session.RetrieveSiteDirectory(); + } + + /// + /// Close the ISession + /// + /// a + public async Task Close() + { + if (!this.IsSessionOpen) + { + return; + } + + await this.Session.Close(); + this.IsSessionOpen = false; + this.CloseIterations(); + } + + /// + /// Open the iteration with the selected and + /// + /// The selected + /// The + public async Task ReadIteration(IterationSetup iterationSetup, DomainOfExpertise domain) + { + var modelSetup = (EngineeringModelSetup)iterationSetup.Container; + var model = new EngineeringModel(modelSetup.EngineeringModelIid, this.Session.Assembler.Cache, this.Session.Credentials.Uri); + + var iteration = new Iteration(iterationSetup.IterationIid, this.Session.Assembler.Cache, this.Session.Credentials.Uri) + { + Container = model + }; + + try + { + await this.Session.Read(iteration, domain); + + if (this.Session.OpenIterations.All(x => x.Key.Iid != iterationSetup.IterationIid)) + { + throw new InvalidOperationException("The requested iteration could not be opened"); + } + + var openedIteration = this.Session.OpenIterations.FirstOrDefault(x => x.Key.Iid == iterationSetup.IterationIid).Key; + this.OpenIterations.Add(openedIteration); + + CDPMessageBus.Current.SendMessage(SessionStateKind.IterationOpened); + } + catch (Exception exception) + { + this.logger.Error($"During read operation an error has occured: {exception.Message}"); + throw; + } + } + + /// + /// Close all the opened + /// + public void CloseIterations() + { + foreach (var iteration in this.OpenIterations.Items.ToList()) + { + this.CloseIteration(iteration); + } + } + + /// + /// Closes an + /// + /// The + public void CloseIteration(Iteration iteration) + { + this.Session.CloseIterationSetup(iteration.IterationSetup); + this.OpenIterations.Remove(this.OpenIterations.Items.First(x => x.Iid == iteration.Iid)); + } + + /// + /// Get available for the ActivePerson + /// + /// + /// A container of + /// + public IEnumerable GetParticipantModels() + { + if (this.IsSessionOpen) + { + return this.GetSiteDirectory().Model + .Where(m => m.Participant.Any(p => p.Person.Name.Equals(this.Session.ActivePerson.Name))); + } + else + { + return Enumerable.Empty(); + } + } + + /// + /// Get available for the active person in the selected + /// + /// + /// The selected + /// + /// A container of accessible for the active person + /// + public IEnumerable GetModelDomains(EngineeringModelSetup modelSetup) + { + var domains = new List(); + modelSetup?.Participant.FindAll(p => p.Person.Iid.Equals(this.Session.ActivePerson.Iid)).ForEach(p => p.Domain.ForEach(d => domains.Add(d))); + return domains.DistinctBy(d => d.Name).OrderBy(d => d.Name); + } + + /// + /// Refresh the ISession object + /// + public async Task RefreshSession() + { + var sw = Stopwatch.StartNew(); + CDPMessageBus.Current.SendMessage(SessionStateKind.Refreshing); + + await this.Session.Refresh(); + + Console.WriteLine($"Session refreshed in {sw.ElapsedMilliseconds} [ms]"); + } + + /// + /// Switches the current domain for an opened iteration + /// + /// The + /// The domain + public void SwitchDomain(Iteration iteration, DomainOfExpertise domainOfExpertise) + { + this.Session.SwitchDomain(iteration.Iid, domainOfExpertise); + } + + /// + /// Write a new Thing in an + /// + /// the container where the should be created + /// the thing to create in the session + /// An asynchronous operation + public async Task CreateThing(Thing container, Thing thingToCreate) + { + await this.CreateThings(container, new List { thingToCreate }); + } + /// /// Write new Things in an /// /// the container where the should be created /// the things to create in the session - /// An asynchronous operation - public async Task CreateThings(Thing container, params Thing[] thingsToCreate) - { - await this.CreateThings(container, thingsToCreate.ToList()); - } - - /// - /// Write new Things in an - /// - /// The where the s should be created - /// List of Things to create in the session - public async Task CreateThings(Thing thing, IEnumerable thingsToCreate) - { - if (thingsToCreate == null) - { - return; - } - - var thingClone = thing; - - if (thing.Original == null) - { - thingClone = thing.Clone(false); - } - - // set the context of the transaction to the thing changes need to be added to. - var context = TransactionContextResolver.ResolveContext(thingClone); - var transaction = new ThingTransaction(context); - - // register new Things and the container Thing (clone) with the transaction. - thingsToCreate.ToList().ForEach(x => { transaction.Create(x, thingClone); }); - - // finalize the transaction, the result is an OperationContainer that the session class uses to write the changes - // to the Thing object. - var operationContainer = transaction.FinalizeTransaction(); - - try - { - await this.Session.Write(operationContainer); - Console.WriteLine("Writing done !"); - } - catch (DalWriteException ex) - { - Console.WriteLine($"The create operation failed: {ex.Message}"); - } - } - - /// - /// Write updated Thing in an - /// - /// The where the s should be updated - /// the thing to update in the session - /// An asynchronous operation - public async Task UpdateThing(Thing container, Thing thingToUpdate) - { - await this.UpdateThings(container, new List { thingToUpdate }); - } - - /// - /// Write updated Things in an - /// - /// The where the s should be updated - /// List of Things to update in the session - /// An asynchronous operation - public async Task UpdateThings(Thing container, params Thing[] thingsToUpdate) - { - await this.UpdateThings(container, thingsToUpdate.ToList()); - } - - /// - /// Write updated Things in an - /// - /// The where the s should be updated - /// List of Things to update in the session - public async Task UpdateThings(Thing thing, IEnumerable thingsToUpdate) - { - if (thingsToUpdate == null) - { - return; - } - - var sw = Stopwatch.StartNew(); - - // CreateThings a shallow clone of the thing. The cached Thing object should not be changed, so we record the change on a clone. - var thingClone = thing; - - if (thing.Original == null) - { - thingClone = thing.Clone(false); - } - - // set the context of the transaction to the thing changes need to be added to. - var context = TransactionContextResolver.ResolveContext(thingClone); - var transaction = new ThingTransaction(context); - - // register all updates with the transaction. - thingsToUpdate.ToList().ForEach(transaction.CreateOrUpdate); - - // finalize the transaction, the result is an OperationContainer that the session class uses to write the changes - // to the Thing object. - var operationContainer = transaction.FinalizeTransaction(); - - try - { - await this.Session.Write(operationContainer); - Console.WriteLine($"Update writing done in {sw.ElapsedMilliseconds} [ms]"); - } - catch (Exception ex) - { - Console.WriteLine($"The update operation failed: {ex.Message}"); - } - finally - { - sw.Stop(); - } - } - - /// - /// Deletes a from it's container - /// - /// the container clone of the thing to delete - /// the cloned thing to delete in the session - /// An asynchronous operation - public async Task DeleteThing(Thing containerClone, Thing thingToDelete) - { - await this.DeleteThings(containerClone, new List { thingToDelete }); - } - - /// - /// Deletes a collection of from it's container - /// - /// the container clone of the thing to delete - /// the cloned things to delete in the session - /// An asynchronous operation - public async Task DeleteThings(Thing containerClone, params Thing[] thingsToDelete) - { - await this.DeleteThings(containerClone, thingsToDelete.ToList()); - } - - /// - /// Deletes a collection from it's container - /// - /// the container clone of the thing to delete - /// the cloned things to delete in the session - /// An asynchronous operation - public async Task DeleteThings(Thing containerClone, IEnumerable thingsToDelete) - { - if (thingsToDelete == null) - { - return; - } - - var sw = Stopwatch.StartNew(); - - // CreateThings a shallow clone of the thing. The cached Thing object should not be changed, so we record the change on a clone. - var thingClone = containerClone; - - if (containerClone.Original == null) - { - thingClone = containerClone.Clone(false); - } - - // set the context of the transaction to the thing changes need to be added to. - var context = TransactionContextResolver.ResolveContext(thingClone); - var transaction = new ThingTransaction(context); - - // register all deletes with the transaction. - foreach (var thingToDelete in thingsToDelete) - { - var thingToDeleteClone = thingToDelete.Clone(false); - transaction.Delete(thingToDeleteClone, containerClone); - } - - // finalize the transaction, the result is an OperationContainer that the session class uses to write the changes - // to the Thing object. - var operationContainer = transaction.FinalizeTransaction(); - - try - { - await this.Session.Write(operationContainer); - Console.WriteLine($"Delete done in {sw.ElapsedMilliseconds} [ms]"); - } - catch (Exception ex) - { - Console.WriteLine($"The delete operation failed: {ex.Message}"); - } - finally - { - sw.Stop(); - } - } - - /// - /// Gets the inside an iteration - /// - public Participant GetParticipant(Iteration iteration) - { - return this.GetSiteDirectory().Model.Find(m => m.IterationSetup.Contains(iteration.IterationSetup))? - .Participant.Find(p => p.Person.Iid == this.Session.ActivePerson.Iid); - } - - /// - /// Gets the for an - /// - /// The - /// The - /// If the is not opened - public DomainOfExpertise GetDomainOfExpertise(Iteration iteration) - { - if (!this.Session.OpenIterations.TryGetValue(iteration, out var participantInformation)) - { - throw new ArgumentException("The requested iteration is not opened"); - } - - return participantInformation.Item1; - } - } -} + /// An asynchronous operation + public async Task CreateThings(Thing container, params Thing[] thingsToCreate) + { + await this.CreateThings(container, thingsToCreate.ToList()); + } + + /// + /// Write new Things in an + /// + /// The where the s should be created + /// List of Things to create in the session + public async Task CreateThings(Thing thing, IEnumerable thingsToCreate) + { + if (thingsToCreate == null) + { + return; + } + + var thingClone = thing; + + if (thing.Original == null) + { + thingClone = thing.Clone(false); + } + + // set the context of the transaction to the thing changes need to be added to. + var context = TransactionContextResolver.ResolveContext(thingClone); + var transaction = new ThingTransaction(context); + + // register new Things and the container Thing (clone) with the transaction. + thingsToCreate.ToList().ForEach(x => { transaction.Create(x, thingClone); }); + + // finalize the transaction, the result is an OperationContainer that the session class uses to write the changes + // to the Thing object. + var operationContainer = transaction.FinalizeTransaction(); + + try + { + await this.Session.Write(operationContainer); + Console.WriteLine("Writing done !"); + } + catch (DalWriteException ex) + { + Console.WriteLine($"The create operation failed: {ex.Message}"); + } + } + + /// + /// Write updated Thing in an + /// + /// The where the s should be updated + /// the thing to update in the session + /// An asynchronous operation + public async Task UpdateThing(Thing container, Thing thingToUpdate) + { + await this.UpdateThings(container, new List { thingToUpdate }); + } + + /// + /// Write updated Things in an + /// + /// The where the s should be updated + /// List of Things to update in the session + /// An asynchronous operation + public async Task UpdateThings(Thing container, params Thing[] thingsToUpdate) + { + await this.UpdateThings(container, thingsToUpdate.ToList()); + } + + /// + /// Write updated Things in an + /// + /// The where the s should be updated + /// List of Things to update in the session + public async Task UpdateThings(Thing thing, IEnumerable thingsToUpdate) + { + if (thingsToUpdate == null) + { + return; + } + + var sw = Stopwatch.StartNew(); + + // CreateThings a shallow clone of the thing. The cached Thing object should not be changed, so we record the change on a clone. + var thingClone = thing; + + if (thing.Original == null) + { + thingClone = thing.Clone(false); + } + + // set the context of the transaction to the thing changes need to be added to. + var context = TransactionContextResolver.ResolveContext(thingClone); + var transaction = new ThingTransaction(context); + + // register all updates with the transaction. + thingsToUpdate.ToList().ForEach(transaction.CreateOrUpdate); + + // finalize the transaction, the result is an OperationContainer that the session class uses to write the changes + // to the Thing object. + var operationContainer = transaction.FinalizeTransaction(); + + try + { + await this.Session.Write(operationContainer); + Console.WriteLine($"Update writing done in {sw.ElapsedMilliseconds} [ms]"); + } + catch (Exception ex) + { + Console.WriteLine($"The update operation failed: {ex.Message}"); + } + finally + { + sw.Stop(); + } + } + + /// + /// Deletes a from it's container + /// + /// the container clone of the thing to delete + /// the cloned thing to delete in the session + /// An asynchronous operation + public async Task DeleteThing(Thing containerClone, Thing thingToDelete) + { + await this.DeleteThings(containerClone, new List { thingToDelete }); + } + + /// + /// Deletes a collection of from it's container + /// + /// the container clone of the thing to delete + /// the cloned things to delete in the session + /// An asynchronous operation + public async Task DeleteThings(Thing containerClone, params Thing[] thingsToDelete) + { + await this.DeleteThings(containerClone, thingsToDelete.ToList()); + } + + /// + /// Deletes a collection from it's container + /// + /// the container clone of the thing to delete + /// the cloned things to delete in the session + /// An asynchronous operation + public async Task DeleteThings(Thing containerClone, IEnumerable thingsToDelete) + { + if (thingsToDelete == null) + { + return; + } + + var sw = Stopwatch.StartNew(); + + // CreateThings a shallow clone of the thing. The cached Thing object should not be changed, so we record the change on a clone. + var thingClone = containerClone; + + if (containerClone.Original == null) + { + thingClone = containerClone.Clone(false); + } + + // set the context of the transaction to the thing changes need to be added to. + var context = TransactionContextResolver.ResolveContext(thingClone); + var transaction = new ThingTransaction(context); + + // register all deletes with the transaction. + foreach (var thingToDelete in thingsToDelete) + { + var thingToDeleteClone = thingToDelete.Clone(false); + transaction.Delete(thingToDeleteClone, containerClone); + } + + // finalize the transaction, the result is an OperationContainer that the session class uses to write the changes + // to the Thing object. + var operationContainer = transaction.FinalizeTransaction(); + + try + { + await this.Session.Write(operationContainer); + Console.WriteLine($"Delete done in {sw.ElapsedMilliseconds} [ms]"); + } + catch (Exception ex) + { + Console.WriteLine($"The delete operation failed: {ex.Message}"); + } + finally + { + sw.Stop(); + } + } + + /// + /// Gets the inside an iteration + /// + public Participant GetParticipant(Iteration iteration) + { + return this.GetSiteDirectory().Model.Find(m => m.IterationSetup.Contains(iteration.IterationSetup))? + .Participant.Find(p => p.Person.Iid == this.Session.ActivePerson.Iid); + } + + /// + /// Gets the for an + /// + /// The + /// The + /// If the is not opened + public DomainOfExpertise GetDomainOfExpertise(Iteration iteration) + { + if (!this.Session.OpenIterations.TryGetValue(iteration, out var participantInformation)) + { + throw new ArgumentException("The requested iteration is not opened"); + } + + return participantInformation.Item1; + } + } +} diff --git a/COMET.Web.Common/Services/StringTableService/BaseStringTableService.cs b/COMET.Web.Common/Services/StringTableService/BaseStringTableService.cs new file mode 100644 index 00000000..6af3d001 --- /dev/null +++ b/COMET.Web.Common/Services/StringTableService/BaseStringTableService.cs @@ -0,0 +1,100 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Services.StringTableService +{ + using COMET.Web.Common.Enumerations; + using COMET.Web.Common.Model; + + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + + /// + /// Base Service implementation that holds the text data from the configuration file + /// + public abstract class BaseStringTableService : IStringTableService + { + /// + /// Initializes a new instance of the class. + /// + /// The + protected BaseStringTableService(ILogger logger) + { + this.Logger = logger; + } + + /// + /// The + /// + protected ILogger Logger { get; } + + /// + /// Gets the file path to load the service + /// + protected string FilePath { get; set; } + + /// + /// The dictionary that contains the map between the configuration and the value + /// + protected Dictionary Configurations { get; set; } = new(); + + /// + /// Value to assert that the service has been initialized + /// + protected bool IsInitialized { get; set; } + + /// + /// Initializes the + /// + /// an asynchronous operation + public abstract Task InitializeService(); + + /// + /// Gets the text asociated to a key + /// + /// the key + /// the text asociated to the key + public string GetText(string key) + { + if (!this.IsInitialized) + { + throw new InvalidOperationException("The Service hasn't been initialized"); + } + + this.Configurations.TryGetValue(key, out var value); + return value; + } + + /// + /// Gets the text asociated to a key + /// + /// the key + /// the text asociated to the key + public string GetText(TextConfigurationKind configurationKind) + { + return this.GetText(configurationKind.ToString()); + } + } +} diff --git a/COMET.Web.Common/Services/StringTableService/IStringTableService.cs b/COMET.Web.Common/Services/StringTableService/IStringTableService.cs new file mode 100644 index 00000000..94f43379 --- /dev/null +++ b/COMET.Web.Common/Services/StringTableService/IStringTableService.cs @@ -0,0 +1,55 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.Services.StringTableService +{ + using COMET.Web.Common.Enumerations; + + /// + /// Service that holds the text data from the configuration file + /// + public interface IStringTableService + { + /// + /// Initializes the + /// + /// an asynchronous operation + Task InitializeService(); + + /// + /// Gets the text asociated to a key + /// + /// the key + /// the text asociated to the key + string GetText(string key); + + /// + /// Gets the text asociated to a key + /// + /// the key + /// the text asociated to the key + string GetText(TextConfigurationKind configurationKind); + } +} diff --git a/COMET.Web.Common/Shared/TopMenuEntry/ApplicationMenu.razor.cs b/COMET.Web.Common/Shared/TopMenuEntry/ApplicationMenu.razor.cs index 6d7d00b6..e35db953 100644 --- a/COMET.Web.Common/Shared/TopMenuEntry/ApplicationMenu.razor.cs +++ b/COMET.Web.Common/Shared/TopMenuEntry/ApplicationMenu.razor.cs @@ -26,8 +26,8 @@ namespace COMET.Web.Common.Shared.TopMenuEntry { using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.RegistrationService; + using COMET.Web.Common.Services.StringTableService; using Microsoft.AspNetCore.Components; @@ -43,9 +43,9 @@ public partial class ApplicationMenu internal IRegistrationService RegistrationService { get; set; } /// - /// The + /// The /// [Inject] - public IConfigurationService ConfigurationService { get; set; } + public IStringTableService ConfigurationService { get; set; } } } diff --git a/COMET.Web.Common/Shared/TopMenuEntry/ModelMenu.razor.cs b/COMET.Web.Common/Shared/TopMenuEntry/ModelMenu.razor.cs index 9fb9d332..5548a8f8 100644 --- a/COMET.Web.Common/Shared/TopMenuEntry/ModelMenu.razor.cs +++ b/COMET.Web.Common/Shared/TopMenuEntry/ModelMenu.razor.cs @@ -27,7 +27,7 @@ namespace COMET.Web.Common.Shared.TopMenuEntry { using CDP4Common.EngineeringModelData; - using COMET.Web.Common.Services.ConfigurationService; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.ViewModels.Shared.TopMenuEntry; using Microsoft.AspNetCore.Components; @@ -46,10 +46,10 @@ public partial class ModelMenu public IModelMenuViewModel ViewModel { get; set; } /// - /// The + /// The /// [Inject] - public IConfigurationService ConfigurationService { get; set; } + public IStringTableService ConfigurationService { get; set; } /// /// Method invoked when the component is ready to start, having received its diff --git a/COMET.Web.Common/ViewModels/Components/ILoginViewModel.cs b/COMET.Web.Common/ViewModels/Components/ILoginViewModel.cs index 9e9bf44c..a4d9bef1 100644 --- a/COMET.Web.Common/ViewModels/Components/ILoginViewModel.cs +++ b/COMET.Web.Common/ViewModels/Components/ILoginViewModel.cs @@ -27,7 +27,7 @@ namespace COMET.Web.Common.ViewModels.Components { using COMET.Web.Common.Enumerations; using COMET.Web.Common.Model.DTO; - using COMET.Web.Common.Services.ServerConnectionService; + using COMET.Web.Common.Services.ConfigurationService; /// /// View Model that enables the user to login against a COMET Server @@ -35,9 +35,9 @@ namespace COMET.Web.Common.ViewModels.Components public interface ILoginViewModel { /// - /// Gets the + /// Gets the /// - IServerConnectionService serverConnectionService { get; } + IConfigurationService serverConnectionService { get; } /// /// Gets or sets the diff --git a/COMET.Web.Common/ViewModels/Components/LoginViewModel.cs b/COMET.Web.Common/ViewModels/Components/LoginViewModel.cs index 59985998..ac917055 100644 --- a/COMET.Web.Common/ViewModels/Components/LoginViewModel.cs +++ b/COMET.Web.Common/ViewModels/Components/LoginViewModel.cs @@ -27,7 +27,7 @@ namespace COMET.Web.Common.ViewModels.Components { using COMET.Web.Common.Enumerations; using COMET.Web.Common.Model.DTO; - using COMET.Web.Common.Services.ServerConnectionService; + using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.SessionManagement; using ReactiveUI; @@ -42,9 +42,9 @@ public class LoginViewModel : ReactiveObject, ILoginViewModel private readonly IAuthenticationService authenticationService; /// - /// Gets the + /// Gets the /// - public IServerConnectionService serverConnectionService { get; } + public IConfigurationService serverConnectionService { get; } /// /// Backing field for @@ -55,7 +55,7 @@ public class LoginViewModel : ReactiveObject, ILoginViewModel /// Initializes a new instance of the class. /// /// The - public LoginViewModel(IAuthenticationService authenticationService, IServerConnectionService serverConnectionService) + public LoginViewModel(IAuthenticationService authenticationService, IConfigurationService serverConnectionService) { this.serverConnectionService = serverConnectionService; this.authenticationService = authenticationService; diff --git a/COMET.Web.Common/ViewModels/Components/OpenModelViewModel.cs b/COMET.Web.Common/ViewModels/Components/OpenModelViewModel.cs index e90c62fb..a3891f74 100644 --- a/COMET.Web.Common/ViewModels/Components/OpenModelViewModel.cs +++ b/COMET.Web.Common/ViewModels/Components/OpenModelViewModel.cs @@ -1,214 +1,213 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023 RHEA System S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar -// -// This file is part of COMET WEB Community Edition -// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 -// Annex A and Annex C. -// -// 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. -// -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace COMET.Web.Common.ViewModels.Components -{ - using CDP4Common.EngineeringModelData; - using CDP4Common.SiteDirectoryData; - - using COMET.Web.Common.Model; - using COMET.Web.Common.Services.ConfigurationService; - using COMET.Web.Common.Services.SessionManagement; - using COMET.Web.Common.Utilities.DisposableObject; - - using DynamicData.Binding; - - using ReactiveUI; - - /// - /// View Model that enables a user to open an - /// - public class OpenModelViewModel : DisposableObject, IOpenModelViewModel - { - /// - /// The - /// - private readonly ISessionService sessionService; - - /// - /// Backing field for - /// - private bool isOpeningSession; - - /// - /// Backing field for - /// - private DomainOfExpertise selectedDomainOfExpertise; - - /// - /// - private EngineeringModelSetup selectedEngineeringModel; - - /// - /// Backing field for - /// +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.ViewModels.Components +{ + using CDP4Common.EngineeringModelData; + using CDP4Common.SiteDirectoryData; + + using COMET.Web.Common.Model; + using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Utilities.DisposableObject; + + using DynamicData.Binding; + + using ReactiveUI; + + /// + /// View Model that enables a user to open an + /// + public class OpenModelViewModel : DisposableObject, IOpenModelViewModel + { + /// + /// The + /// + private readonly ISessionService sessionService; + + /// + /// Backing field for + /// + private bool isOpeningSession; + + /// + /// Backing field for + /// + private DomainOfExpertise selectedDomainOfExpertise; + + /// + /// + private EngineeringModelSetup selectedEngineeringModel; + + /// + /// Backing field for + /// private IterationData selectedIterationSetup; - /// - /// Initializes a new instance of the class. - /// - /// The - public OpenModelViewModel(ISessionService sessionService) - { - this.sessionService = sessionService; - - this.Disposables.Add(this.WhenAnyPropertyChanged(nameof(this.SelectedEngineeringModel)) - .Subscribe(_ => this.ComputeAvailableCollections())); - } - - /// - /// The selected - /// - public EngineeringModelSetup SelectedEngineeringModel - { - get => this.selectedEngineeringModel; - set => this.RaiseAndSetIfChanged(ref this.selectedEngineeringModel, value); - } - - /// - /// The selected - /// - public IterationData SelectedIterationSetup - { - get => this.selectedIterationSetup; - set => this.RaiseAndSetIfChanged(ref this.selectedIterationSetup, value); - } - - /// - /// The selected - /// - public DomainOfExpertise SelectedDomainOfExpertise - { - get => this.selectedDomainOfExpertise; - set => this.RaiseAndSetIfChanged(ref this.selectedDomainOfExpertise, value); - } - - /// - /// A collection of available - /// - public IEnumerable AvailableEngineeringModelSetups { get; set; } - - /// - /// A collection of available - /// - public IEnumerable AvailableIterationSetups { get; set; } - - /// - /// A collection of available - /// - public IEnumerable AvailablesDomainOfExpertises { get; set; } - - /// - /// Value asserting that the session is on way to open - /// - public bool IsOpeningSession - { - get => this.isOpeningSession; - set => this.RaiseAndSetIfChanged(ref this.isOpeningSession, value); - } - - /// - /// Initializes this view model properties - /// - public void InitializesProperties() - { - this.SelectedDomainOfExpertise = null; - this.SelectedEngineeringModel = null; - this.SelectedIterationSetup = null; - this.IsOpeningSession = false; - - this.AvailableEngineeringModelSetups = this.sessionService.GetParticipantModels() - .Where(x => x.IterationSetup.Any(setup => this.sessionService.OpenIterations.Items.All(i => i.Iid != setup.IterationIid))) - .OrderBy(x => x.Name); - } - - /// - /// Opens the based on the selected field - /// - /// - public async Task OpenSession() - { - if (this.SelectedIterationSetup != null && this.SelectedDomainOfExpertise != null) - { - this.IsOpeningSession = true; - - await this.sessionService.ReadIteration(this.SelectedEngineeringModel.IterationSetup - .First(x => x.Iid == this.SelectedIterationSetup.IterationSetupId), this.SelectedDomainOfExpertise); - - this.IsOpeningSession = false; - } - } - - /// - /// Preselects the to open - /// - /// The of the - /// The of the to open - /// The of the to select - public void PreSelectIteration(Guid modelId, Guid iterationId, Guid domainId) - { - this.selectedEngineeringModel = this.AvailableEngineeringModelSetups.FirstOrDefault(x => x.Iid == modelId); - var iterationSetup = this.SelectedEngineeringModel?.IterationSetup.FirstOrDefault(x => x.IterationIid == iterationId); - - if (iterationSetup != null) - { - this.SelectedIterationSetup = new IterationData(iterationSetup); - } - - this.AvailablesDomainOfExpertises = this.sessionService.GetModelDomains(this.SelectedEngineeringModel); - this.SelectedDomainOfExpertise = this.AvailablesDomainOfExpertises.FirstOrDefault(x => x.Iid == domainId); - } - - /// - /// Compute the available collection based on the selected - /// - private void ComputeAvailableCollections() - { - if (this.SelectedEngineeringModel == null) - { - this.AvailablesDomainOfExpertises = new List(); - this.AvailableIterationSetups = new List(); - this.SelectedDomainOfExpertise = null; - this.SelectedIterationSetup = null; - } - else - { - this.SelectedIterationSetup = this.selectedEngineeringModel.IterationSetup - .Where(x => x.FrozenOn == null) - .Select(x => new IterationData(x)) - .LastOrDefault(); - - this.SelectedDomainOfExpertise = this.SelectedEngineeringModel.ActiveDomain.FirstOrDefault(x => x == this.sessionService.Session.ActivePerson.DefaultDomain); - - this.AvailablesDomainOfExpertises = this.sessionService.GetModelDomains(this.SelectedEngineeringModel); - - this.AvailableIterationSetups = this.SelectedEngineeringModel.IterationSetup - .Where(x => this.sessionService.OpenIterations.Items.All(i => i.Iid != x.IterationIid)) - .OrderBy(x => x.IterationNumber) - .Select(x => new IterationData(x)); - } - } - } -} + /// + /// Initializes a new instance of the class. + /// + /// The + public OpenModelViewModel(ISessionService sessionService) + { + this.sessionService = sessionService; + + this.Disposables.Add(this.WhenAnyPropertyChanged(nameof(this.SelectedEngineeringModel)) + .Subscribe(_ => this.ComputeAvailableCollections())); + } + + /// + /// The selected + /// + public EngineeringModelSetup SelectedEngineeringModel + { + get => this.selectedEngineeringModel; + set => this.RaiseAndSetIfChanged(ref this.selectedEngineeringModel, value); + } + + /// + /// The selected + /// + public IterationData SelectedIterationSetup + { + get => this.selectedIterationSetup; + set => this.RaiseAndSetIfChanged(ref this.selectedIterationSetup, value); + } + + /// + /// The selected + /// + public DomainOfExpertise SelectedDomainOfExpertise + { + get => this.selectedDomainOfExpertise; + set => this.RaiseAndSetIfChanged(ref this.selectedDomainOfExpertise, value); + } + + /// + /// A collection of available + /// + public IEnumerable AvailableEngineeringModelSetups { get; set; } + + /// + /// A collection of available + /// + public IEnumerable AvailableIterationSetups { get; set; } + + /// + /// A collection of available + /// + public IEnumerable AvailablesDomainOfExpertises { get; set; } + + /// + /// Value asserting that the session is on way to open + /// + public bool IsOpeningSession + { + get => this.isOpeningSession; + set => this.RaiseAndSetIfChanged(ref this.isOpeningSession, value); + } + + /// + /// Initializes this view model properties + /// + public void InitializesProperties() + { + this.SelectedDomainOfExpertise = null; + this.SelectedEngineeringModel = null; + this.SelectedIterationSetup = null; + this.IsOpeningSession = false; + + this.AvailableEngineeringModelSetups = this.sessionService.GetParticipantModels() + .Where(x => x.IterationSetup.Any(setup => this.sessionService.OpenIterations.Items.All(i => i.Iid != setup.IterationIid))) + .OrderBy(x => x.Name); + } + + /// + /// Opens the based on the selected field + /// + /// + public async Task OpenSession() + { + if (this.SelectedIterationSetup != null && this.SelectedDomainOfExpertise != null) + { + this.IsOpeningSession = true; + + await this.sessionService.ReadIteration(this.SelectedEngineeringModel.IterationSetup + .First(x => x.Iid == this.SelectedIterationSetup.IterationSetupId), this.SelectedDomainOfExpertise); + + this.IsOpeningSession = false; + } + } + + /// + /// Preselects the to open + /// + /// The of the + /// The of the to open + /// The of the to select + public void PreSelectIteration(Guid modelId, Guid iterationId, Guid domainId) + { + this.selectedEngineeringModel = this.AvailableEngineeringModelSetups.FirstOrDefault(x => x.Iid == modelId); + var iterationSetup = this.SelectedEngineeringModel?.IterationSetup.FirstOrDefault(x => x.IterationIid == iterationId); + + if (iterationSetup != null) + { + this.SelectedIterationSetup = new IterationData(iterationSetup); + } + + this.AvailablesDomainOfExpertises = this.sessionService.GetModelDomains(this.SelectedEngineeringModel); + this.SelectedDomainOfExpertise = this.AvailablesDomainOfExpertises.FirstOrDefault(x => x.Iid == domainId); + } + + /// + /// Compute the available collection based on the selected + /// + private void ComputeAvailableCollections() + { + if (this.SelectedEngineeringModel == null) + { + this.AvailablesDomainOfExpertises = new List(); + this.AvailableIterationSetups = new List(); + this.SelectedDomainOfExpertise = null; + this.SelectedIterationSetup = null; + } + else + { + this.SelectedIterationSetup = this.selectedEngineeringModel.IterationSetup + .Where(x => x.FrozenOn == null) + .Select(x => new IterationData(x)) + .LastOrDefault(); + + this.SelectedDomainOfExpertise = this.SelectedEngineeringModel.ActiveDomain.FirstOrDefault(x => x == this.sessionService.Session.ActivePerson.DefaultDomain); + + this.AvailablesDomainOfExpertises = this.sessionService.GetModelDomains(this.SelectedEngineeringModel); + + this.AvailableIterationSetups = this.SelectedEngineeringModel.IterationSetup + .Where(x => this.sessionService.OpenIterations.Items.All(i => i.Iid != x.IterationIid)) + .OrderBy(x => x.IterationNumber) + .Select(x => new IterationData(x)); + } + } + } +} diff --git a/COMET.Web.Common/Services/ServerConnectionService/ServerConnectionService.cs b/COMET.Web.Common/WebAssembly/Services/ConfigurationService/ConfigurationService.cs similarity index 51% rename from COMET.Web.Common/Services/ServerConnectionService/ServerConnectionService.cs rename to COMET.Web.Common/WebAssembly/Services/ConfigurationService/ConfigurationService.cs index b072581c..e0c05d37 100644 --- a/COMET.Web.Common/Services/ServerConnectionService/ServerConnectionService.cs +++ b/COMET.Web.Common/WebAssembly/Services/ConfigurationService/ConfigurationService.cs @@ -1,5 +1,5 @@ // -------------------------------------------------------------------------------------------------------------------- -// +// // Copyright (c) 2023 RHEA System S.A. // // Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar @@ -22,95 +22,90 @@ // // // -------------------------------------------------------------------------------------------------------------------- -namespace COMET.Web.Common.Services.ServerConnectionService + +namespace COMET.Web.Common.WebAssembly.Services.ConfigurationService { - using System; using System.Net; using System.Text.Json; using COMET.Web.Common.Model; + using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Utilities; + using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; /// - /// Service that holds the text data from the configuration file + /// Service that holds the configuration for the application /// - public class ServerConnectionService : IServerConnectionService + public class ConfigurationService : BaseConfigurationService { /// - /// The json file that contains the server configuration + /// The used to retrieve the json /// - private readonly string ServerConfigurationFile; + private readonly HttpClient http; /// - /// The Server Address to use + /// The json file that contains the server configuration /// - public string ServerAddress { get; private set; } + private readonly string serverConfigurationFile; /// - /// The used to retrieve the json + /// Gets the /// - private readonly HttpClient http; + private readonly ILogger logger; /// - /// Value to assert that the service has been initialized + /// Creates a new instance of type /// - private bool isInitialized; - - /// - /// Creates a new instance of type - /// - /// the - /// the - public ServerConnectionService(IOptions options, HttpClient httpClient) + /// the + /// the + /// The + public ConfigurationService(IOptions options, HttpClient httpClient, ILogger logger) { - this.ServerConfigurationFile = options.Value.ServerConfigurationFile ?? "server_configuration.json"; + this.serverConfigurationFile = options.Value.ServerConfigurationFile ?? "server_configuration.json"; this.http = httpClient; + this.logger = logger; } /// - /// Initializes the + /// Initializes the /// /// an asynchronous operation - public async Task InitializeService() + public override async Task InitializeService() { - Dictionary configurations = new Dictionary(); - - if (this.isInitialized) + if (this.IsInitialized) { return; } try { - var path = ContentPathBuilder.BuildPath(this.ServerConfigurationFile); + var path = ContentPathBuilder.BuildPath(this.serverConfigurationFile); + using var response = await this.http.GetAsync(path); - using (var response = await this.http.GetAsync(path)) + if (response.IsSuccessStatusCode) + { + var jsonContent = await response.Content.ReadAsStreamAsync(); + var configurations = JsonSerializer.Deserialize>(jsonContent); + this.ServerAddress = configurations["ServerAddress"]; + } + else if (response.StatusCode == HttpStatusCode.NotFound) + { + this.logger.LogError("Server configuration file not found at {path}", path); + } + else { - if (response.IsSuccessStatusCode) - { - var jsonContent = await response.Content.ReadAsStreamAsync(); - configurations = JsonSerializer.Deserialize>(jsonContent); - this.ServerAddress = configurations["ServerAddress"]; - } - else if (response.StatusCode == HttpStatusCode.NotFound) - { - Console.WriteLine($"Server configuration file not found at {path}"); - } - else - { - Console.WriteLine($"Error fetching server configuration. Status code: {response.StatusCode}"); - } + this.logger.LogError("Error fetching server configuration. Status code: {response}", response.StatusCode); } } catch (Exception e) { - Console.WriteLine(e); + this.logger.LogCritical("Exception has been raised : {message}", e.Message); return; } - this.isInitialized = true; + this.IsInitialized = true; } } } diff --git a/COMET.Web.Common/WebAssembly/Services/StringTableService/StringTableService.cs b/COMET.Web.Common/WebAssembly/Services/StringTableService/StringTableService.cs new file mode 100644 index 00000000..f430e690 --- /dev/null +++ b/COMET.Web.Common/WebAssembly/Services/StringTableService/StringTableService.cs @@ -0,0 +1,85 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2023 RHEA System S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 +// Annex A and Annex C. +// +// 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. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace COMET.Web.Common.WebAssembly.Services.StringTableService +{ + using System.Text.Json; + + using COMET.Web.Common.Model; + using COMET.Web.Common.Services.StringTableService; + using COMET.Web.Common.Utilities; + + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + + /// + /// Service that holds the text data from the configuration file + /// + public class StringTableService : BaseStringTableService + { + /// + /// The used to retrieve the json + /// + private readonly HttpClient http; + + /// + /// Creates a new instance of type + /// + /// the + /// the + /// the + public StringTableService(IOptions options, HttpClient httpClient, ILogger logger):base( logger) + { + this.FilePath = options.Value.JsonConfigurationFile ?? "DefaultTextConfiguration.json"; + this.http = httpClient; + } + + /// + /// Initializes the + /// + /// an asynchronous operation + public override async Task InitializeService() + { + if (this.IsInitialized) + { + return; + } + + try + { + var path = ContentPathBuilder.BuildPath(this.FilePath); + var jsonContent = await this.http.GetStreamAsync(path); + this.Configurations = JsonSerializer.Deserialize>(jsonContent); + } + catch (Exception e) + { + this.Logger.LogError(e, "Error while getting the configuration file."); + return; + } + + this.IsInitialized = true; + } + } +} diff --git a/COMET.Web.Common/_Imports.razor b/COMET.Web.Common/_Imports.razor index d25b4d85..e65fc98f 100644 --- a/COMET.Web.Common/_Imports.razor +++ b/COMET.Web.Common/_Imports.razor @@ -17,7 +17,6 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.JSInterop @using DevExpress.Blazor diff --git a/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs b/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs index 63b14f68..e47a7821 100644 --- a/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs +++ b/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs @@ -35,12 +35,11 @@ namespace COMETwebapp.Tests.Pages.ModelDashboard using COMET.Web.Common.Components.Selectors; using COMET.Web.Common.Extensions; using COMET.Web.Common.Services.ConfigurationService; - using COMET.Web.Common.Services.ServerConnectionService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.ViewModels.Components; using COMET.Web.Common.ViewModels.Components.Selectors; - using COMETwebapp.Pages.ModelDashboard; using COMETwebapp.ViewModels.Components.ModelDashboard; using COMETwebapp.ViewModels.Components.ModelDashboard.ParameterValues; @@ -116,14 +115,14 @@ public void Setup() this.context.ConfigureDevExpressBlazor(); this.context.Services.AddSingleton(this.viewModel); this.context.Services.AddSingleton(this.sessionService.Object); - this.context.Services.AddSingleton(); + this.context.Services.AddSingleton(new Mock().Object); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); - var configurationService = new Mock(); - configurationService.Setup(x => x.GetText(It.IsAny())).Returns("something"); - this.context.Services.AddSingleton(configurationService.Object); + var stringTableService = new Mock(); + stringTableService.Setup(x => x.GetText(It.IsAny())).Returns("something"); + this.context.Services.AddSingleton(stringTableService.Object); } [TearDown] diff --git a/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs b/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs index 682083df..8658dab0 100644 --- a/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs +++ b/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs @@ -36,12 +36,11 @@ namespace COMETwebapp.Tests.Pages.ParameterEditor using COMET.Web.Common.Extensions; using COMET.Web.Common.Services.ConfigurationService; using COMET.Web.Common.Services.NotificationService; - using COMET.Web.Common.Services.ServerConnectionService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.ViewModels.Components; using COMET.Web.Common.ViewModels.Components.Selectors; - using COMETwebapp.Pages.ParameterEditor; using COMETwebapp.Services.SubscriptionService; using COMETwebapp.ViewModels.Components.ParameterEditor; @@ -123,9 +122,9 @@ public void Setup() this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); - this.context.Services.AddSingleton(); + this.context.Services.AddSingleton(new Mock().Object); - var configurationService = new Mock(); + var configurationService = new Mock(); configurationService.Setup(x => x.GetText(It.IsAny())).Returns("something"); this.context.Services.AddSingleton(configurationService.Object); } diff --git a/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs b/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs index 3ea0bd9d..aa770d10 100644 --- a/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs +++ b/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs @@ -25,40 +25,39 @@ namespace COMETwebapp.Tests.Pages.Viewer { using Bunit; - + using CDP4Common.EngineeringModelData; using CDP4Common.SiteDirectoryData; - + using CDP4Dal; using COMET.Web.Common.Components; using COMET.Web.Common.Components.Selectors; using COMET.Web.Common.Extensions; using COMET.Web.Common.Services.ConfigurationService; - using COMET.Web.Common.Services.ServerConnectionService; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Services.StringTableService; using COMET.Web.Common.Test.Helpers; using COMET.Web.Common.ViewModels.Components; using COMET.Web.Common.ViewModels.Components.Selectors; - using COMETwebapp.Pages.Viewer; using COMETwebapp.Services.Interoperability; using COMETwebapp.Services.SubscriptionService; using COMETwebapp.Utilities; using COMETwebapp.ViewModels.Components.Viewer; - + using DevExpress.Blazor; - + using DynamicData; - + using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Microsoft.Extensions.DependencyInjection; - + using Moq; - + using NUnit.Framework; - + using TestContext = Bunit.TestContext; [TestFixture] @@ -121,12 +120,12 @@ public void Setup() this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); - this.context.Services.AddSingleton(); + this.context.Services.AddSingleton(new Mock().Object); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); this.context.Services.AddSingleton(); - var configurationService = new Mock(); + var configurationService = new Mock(); configurationService.Setup(x => x.GetText(It.IsAny())).Returns("something"); this.context.Services.AddSingleton(configurationService.Object); } diff --git a/COMETwebapp.sln.DotSettings b/COMETwebapp.sln.DotSettings index cb1f87e7..fad6fc78 100644 --- a/COMETwebapp.sln.DotSettings +++ b/COMETwebapp.sln.DotSettings @@ -255,7 +255,7 @@ <copyright file="$FILENAME$" company="RHEA System S.A."> Copyright (c) $CURRENT_YEAR$ RHEA System S.A. - Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar + Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine This file is part of COMET WEB Community Edition The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. diff --git a/COMETwebapp/Program.cs b/COMETwebapp/Program.cs index 9546ef2c..5f7f0f0c 100644 --- a/COMETwebapp/Program.cs +++ b/COMETwebapp/Program.cs @@ -47,11 +47,14 @@ namespace COMETwebapp using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using System.Diagnostics.CodeAnalysis; - using System.Reflection; + using COMET.Web.Common; + using COMETwebapp.ViewModels.Components.BookEditor; + using Microsoft.AspNetCore.Components.Web; + /// /// Point of entry of the application /// @@ -65,18 +68,26 @@ public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); - builder.AddCometWebCommon(options => + builder.RootComponents.Add("#app"); + builder.RootComponents.Add("head::after"); + + builder.Services.RegisterCommonLibrary(false, options => { options.Applications = Applications.ExistingApplications; options.AdditionalAssemblies.Add(Assembly.GetAssembly(typeof(Program))); options.AdditionalMenuEntries.AddRange(new List{typeof(ShowHideDeprecatedThings), typeof(AboutMenu)}); }); + + builder.Services.AddScoped(_ => new HttpClient() + { + BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) + }); RegisterServices(builder); RegisterViewModels(builder); var host = builder.Build(); - await host.InitializeServices(); + await host.Services.InitializeServices(); await host.RunAsync(); } @@ -86,7 +97,7 @@ public static async Task Main(string[] args) /// The public static void RegisterServices(WebAssemblyHostBuilder builder) { - builder.Services.AddSingleton(); + builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton();