diff --git a/COMETwebapp.Tests/Components/Viewer/PropertiesPanel/PropertiesComponentTestFixture.cs b/COMETwebapp.Tests/Components/Viewer/PropertiesPanel/PropertiesComponentTestFixture.cs index 0f6d1f83..452ee084 100644 --- a/COMETwebapp.Tests/Components/Viewer/PropertiesPanel/PropertiesComponentTestFixture.cs +++ b/COMETwebapp.Tests/Components/Viewer/PropertiesPanel/PropertiesComponentTestFixture.cs @@ -1,26 +1,26 @@ // -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023-2024 Starion Group S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar -// -// This file is part of CDP4-COMET WEB Community Edition -// The CDP4-COMET WEB Community Edition is the Starion Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. -// -// The CDP4-COMET WEB Community Edition is free software; you can redistribute it and/or -// modify it under the terms of the GNU Affero General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// The CDP4-COMET WEB Community Edition is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// +// Copyright (c) 2024 Starion Group S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, João Rua +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the Starion Group Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. +// +// The COMET WEB Community Edition is free software; you can redistribute it and/or +// modify it under the terms of the GNU Affero General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// The COMET WEB Community Edition is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -// -// -------------------------------------------------------------------------------------------------------------------- +// +// -------------------------------------------------------------------------------------------------------------------- namespace COMETwebapp.Tests.Components.Viewer.PropertiesPanel { @@ -33,6 +33,7 @@ namespace COMETwebapp.Tests.Components.Viewer.PropertiesPanel using CDP4Dal; using COMET.Web.Common.Services.SessionManagement; + using COMET.Web.Common.Test.Helpers; using COMETwebapp.Components.Viewer.PropertiesPanel; using COMETwebapp.Model; @@ -63,6 +64,7 @@ public class PropertiesComponentTestFixture public void SetUp() { this.context = new TestContext(); + this.context.ConfigureDevExpressBlazor(); var babylonService = new Mock(); this.context.Services.AddSingleton(babylonService); @@ -81,13 +83,10 @@ public void SetUp() this.viewModel = new PropertiesComponentViewModel(babylonService.Object, sessionService.Object, selectionMediator.Object, this.messageBus) { IsVisible = true, - ParameterValueSetRelations = new Dictionary() + ParameterValueSetRelations = [] }; - this.renderedComponent = this.context.RenderComponent(parameters => - { - parameters.Add(p => p.ViewModel, this.viewModel); - }); + this.renderedComponent = this.context.RenderComponent(parameters => { parameters.Add(p => p.ViewModel, this.viewModel); }); this.properties = this.renderedComponent.Instance; } @@ -96,6 +95,8 @@ public void SetUp() public void Teardown() { this.messageBus.ClearSubscriptions(); + this.context.CleanContext(); + this.context.Dispose(); } [Test] @@ -108,22 +109,12 @@ public void VerifyComponent() }); } - [Test] - public void VerifyThatComponentCanBeHidden() - { - this.properties.ViewModel.IsVisible = true; - var component = this.renderedComponent.Find("#properties-header"); - Assert.That(component, Is.Not.Null); - this.properties.ViewModel.IsVisible = false; - Assert.Throws(() => this.renderedComponent.Find("#properties-header")); - } - [Test] public void VerifyElementValueChanges() { var compoundData = new OrderedItemList(null) { - new ParameterTypeComponent + new() { Iid = Guid.NewGuid(), ShortName = "firstValue", @@ -147,13 +138,13 @@ public void VerifyElementValueChanges() parametertype.Component.AddRange(compoundData); - var parameter = new Parameter() { Iid = Guid.NewGuid(), ParameterType = parametertype }; + var parameter = new Parameter { Iid = Guid.NewGuid(), ParameterType = parametertype }; this.viewModel.SelectedParameter = parameter; var compoundValues = new List { "1" }; - var parameterValueSet = new ParameterValueSet() + var parameterValueSet = new ParameterValueSet { Iid = Guid.NewGuid(), ValueSwitch = ParameterSwitchKind.MANUAL, @@ -168,15 +159,25 @@ public void VerifyElementValueChanges() }); var compoundValues1 = new List { "false" }; - - var parameterValueSet1 = new ParameterValueSet() + + var parameterValueSet1 = new ParameterValueSet { Iid = Guid.NewGuid(), ValueSwitch = ParameterSwitchKind.MANUAL, - Manual = new ValueArray(compoundValues1), + Manual = new ValueArray(compoundValues1) }; - - Assert.That(() => this.viewModel.ParameterValueSetChanged((parameterValueSet1,0)), Throws.Nothing); + + Assert.That(() => this.viewModel.ParameterValueSetChanged((parameterValueSet1, 0)), Throws.Nothing); + } + + [Test] + public void VerifyThatComponentCanBeHidden() + { + this.properties.ViewModel.IsVisible = true; + var component = this.renderedComponent.Find("#properties-header"); + Assert.That(component, Is.Not.Null); + this.properties.ViewModel.IsVisible = false; + Assert.Throws(() => this.renderedComponent.Find("#properties-header")); } } } diff --git a/COMETwebapp/Components/ParameterEditor/ParameterTable.razor b/COMETwebapp/Components/ParameterEditor/ParameterTable.razor index 0005ed75..a53f0250 100644 --- a/COMETwebapp/Components/ParameterEditor/ParameterTable.razor +++ b/COMETwebapp/Components/ParameterEditor/ParameterTable.razor @@ -76,7 +76,16 @@ CustomizeElement="this.OnCustomizeElement"> - + + + @context.DisplayText + + @if (context.DataItem is ParameterBaseRowViewModel { Parameter: ParameterOverride }) + { + [Override] + } + + diff --git a/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor b/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor index 638c2410..e3d8129b 100644 --- a/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor +++ b/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor @@ -1,7 +1,7 @@  - -@using CDP4Dal +@inherits DisposableComponent
- @if (this.ViewModel.IsVisible) + @if (this.ViewModel.IsVisible) { - var selectedSceneObject = this.ViewModel.SelectionMediator.SelectedSceneObject; - var title = selectedSceneObject is not null ? selectedSceneObject.ElementBase.Name + " - Properties:" : "Properties"; - var buttonClass = this.ViewModel.ParameterHaveChanges ? "submit-button button-blue" : "submit-button"; -
-

@title

- +

@(this.Title)

+
@{ - var parameters = this.ViewModel.ParametersInUse is not null ? this.ViewModel.ParametersInUse : new List(); + var parameters = this.ViewModel.ParametersInUse ?? []; + @foreach (var parameter in parameters) { var classNames = parameter == this.ViewModel.SelectedParameter ? "parameter-item parameter-item-selected" : "parameter-item"; -

@parameter.ParameterType?.Name

+

@parameter.ParameterType?.Name

} }
diff --git a/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor.cs b/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor.cs index 592e5715..c6b4278c 100644 --- a/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor.cs +++ b/COMETwebapp/Components/Viewer/PropertiesPanel/PropertiesComponent.razor.cs @@ -1,46 +1,54 @@ // -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2023-2024 Starion Group S.A. -// -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar -// -// This file is part of CDP4-COMET WEB Community Edition -// The CDP4-COMET WEB Community Edition is the Starion Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. -// -// The CDP4-COMET WEB Community Edition is free software; you can redistribute it and/or -// modify it under the terms of the GNU Affero General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// The CDP4-COMET WEB Community Edition is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// +// Copyright (c) 2024 Starion Group S.A. +// +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, João Rua +// +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the Starion Group Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. +// +// The COMET WEB Community Edition is free software; you can redistribute it and/or +// modify it under the terms of the GNU Affero General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// The COMET WEB Community Edition is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Affero General Public License for more details. -// +// // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -// -// -------------------------------------------------------------------------------------------------------------------- +// +// -------------------------------------------------------------------------------------------------------------------- namespace COMETwebapp.Components.Viewer.PropertiesPanel { + using COMET.Web.Common.Components; + using COMET.Web.Common.Extensions; + using COMETwebapp.ViewModels.Components.Viewer.PropertiesPanel; - + using Microsoft.AspNetCore.Components; - - using ReactiveUI; + + using ReactiveUI; /// /// The properties component used for displaying data about the selected primitive /// - public partial class PropertiesComponent - { + public partial class PropertiesComponent : DisposableComponent + { /// - /// Gets or sets the + /// Gets or sets the /// [Parameter] - public IPropertiesComponentViewModel ViewModel { get; set; } - + public IPropertiesComponentViewModel ViewModel { get; set; } + + /// + /// Gets the properties component title + /// + private string Title => this.ViewModel.SelectionMediator.SelectedSceneObject is not null ? this.ViewModel.SelectionMediator.SelectedSceneObject.ElementBase.Name + " - Properties:" : "Properties"; + /// /// Method invoked when the component is ready to start, having received its /// initial parameters from its parent in the render tree. @@ -49,9 +57,11 @@ protected override void OnInitialized() { base.OnInitialized(); - this.WhenAnyValue(x => x.ViewModel.IsVisible, - x => x.ViewModel.SelectedParameter, - x => x.ViewModel.ParameterHaveChanges).Subscribe(_ => this.InvokeAsync(this.StateHasChanged)); + this.Disposables.Add(this.WhenAnyValue( + x => x.ViewModel.IsVisible, + x => x.ViewModel.SelectedParameter, + x => x.ViewModel.ParameterHaveChanges) + .SubscribeAsync(_ => this.InvokeAsync(this.StateHasChanged))); } } } diff --git a/COMETwebapp/Components/Viewer/ViewerBody.razor.css b/COMETwebapp/Components/Viewer/ViewerBody.razor.css index 67aa75a3..1ee626a8 100644 --- a/COMETwebapp/Components/Viewer/ViewerBody.razor.css +++ b/COMETwebapp/Components/Viewer/ViewerBody.razor.css @@ -6,6 +6,7 @@ grid-template-rows: 1fr; grid-column-gap: 0px; grid-row-gap: 0px; + gap: 10px; } #leftColumn { diff --git a/COMETwebapp/ViewModels/Components/Viewer/ViewerProductTreeViewModel.cs b/COMETwebapp/ViewModels/Components/Viewer/ViewerProductTreeViewModel.cs index 223a3392..bd16ec2a 100644 --- a/COMETwebapp/ViewModels/Components/Viewer/ViewerProductTreeViewModel.cs +++ b/COMETwebapp/ViewModels/Components/Viewer/ViewerProductTreeViewModel.cs @@ -1,18 +1,18 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2023-2024 Starion Group S.A. +// Copyright (c) 2024 Starion Group S.A. // -// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine +// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, João Rua // -// This file is part of CDP4-COMET WEB Community Edition -// The CDP4-COMET WEB Community Edition is the Starion Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. +// This file is part of COMET WEB Community Edition +// The COMET WEB Community Edition is the Starion Group Web Application implementation of ECSS-E-TM-10-25 Annex A and Annex C. // -// The CDP4-COMET WEB Community Edition is free software; you can redistribute it and/or +// The COMET WEB Community Edition is free software; you can redistribute it and/or // modify it under the terms of the GNU Affero General Public // License as published by the Free Software Foundation; either // version 3 of the License, or (at your option) any later version. // -// The CDP4-COMET WEB Community Edition is distributed in the hope that it will be useful, +// The COMET WEB Community Edition is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Affero General Public License for more details. @@ -31,6 +31,7 @@ namespace COMETwebapp.ViewModels.Components.Viewer using COMETwebapp.Model; using COMETwebapp.Utilities; using COMETwebapp.ViewModels.Components.Shared; + using ReactiveUI; /// @@ -38,11 +39,6 @@ namespace COMETwebapp.ViewModels.Components.Viewer /// public class ViewerProductTreeViewModel : ProductTreeViewModel { - /// - /// Gets o sets the - /// - public ISelectionMediator SelectionMediator { get; private set; } - /// /// Creates a new instance of type /// @@ -58,6 +54,11 @@ public ViewerProductTreeViewModel(ISelectionMediator selectionMediator) this.Disposables.Add(this.WhenAnyValue(x => x.SelectedFilter).Subscribe(_ => this.OnFilterChanged())); } + /// + /// Gets o sets the + /// + public ISelectionMediator SelectionMediator { get; private set; } + /// /// Creates the product tree /// @@ -69,25 +70,66 @@ public override ViewerNodeViewModel CreateTree(IEnumerable productT { var treeElements = productTreeElements.ToList(); - if (treeElements.Any() && selectedOption != null && selectedActualFiniteStates != null) + if (treeElements.Count == 0 || selectedOption == null || selectedActualFiniteStates == null) { - var topElement = treeElements.First(); - var states = selectedActualFiniteStates.ToList(); + return this.RootViewModel; + } - var topSceneObject = SceneObject.Create(topElement, selectedOption, states); + var topElement = treeElements.First(); + var states = selectedActualFiniteStates.ToList(); - this.RootViewModel = new ViewerNodeViewModel(topSceneObject) - { - SelectionMediator = this.SelectionMediator - }; + var topSceneObject = SceneObject.Create(topElement, selectedOption, states); - this.CreateTreeRecursively(topElement, this.RootViewModel, null, selectedOption, states); - this.RootViewModel.OrderAllDescendantsByShortName(); - } + this.RootViewModel = new ViewerNodeViewModel(topSceneObject) + { + SelectionMediator = this.SelectionMediator + }; + + this.CreateTreeRecursively(topElement, this.RootViewModel, null, selectedOption, states); + this.RootViewModel.OrderAllDescendantsByShortName(); return this.RootViewModel; } + /// + /// Event for when the filter on the tree changes + /// + public override void OnFilterChanged() + { + var fullTree = this.RootViewModel?.GetFlatListOfDescendants(true); + + if (fullTree is null) + { + return; + } + + if (this.SelectedFilter == TreeFilter.ShowNodesWithGeometry) + { + fullTree.ForEach(x => { x.IsDrawn = x.SceneObject.Primitive != null; }); + } + else + { + fullTree.ForEach(x => x.IsDrawn = true); + } + } + + /// + /// Event for when the text of the search filter is changing + /// + public override void OnSearchFilterChange() + { + var fullTree = this.RootViewModel?.GetFlatListOfDescendants(true); + + if (this.SearchText == string.Empty) + { + fullTree?.ForEach(x => x.IsDrawn = true); + } + else + { + fullTree?.ForEach(x => { x.IsDrawn = x.Title.Contains(this.SearchText, StringComparison.InvariantCultureIgnoreCase); }); + } + } + /// /// Creates the tree in a recursive way /// @@ -125,9 +167,14 @@ protected override void CreateTreeRecursively(ElementBase elementBase, ViewerNod /// /// Callback for when a model has been selected /// - /// the selected + /// the selected private void OnModelSelectionChanged(SceneObject sceneObject) { + if (this.RootViewModel is null) + { + return; + } + var treeNodes = this.RootViewModel.GetFlatListOfDescendants(); treeNodes.ForEach(x => x.IsSelected = false); @@ -143,47 +190,5 @@ private void OnModelSelectionChanged(SceneObject sceneObject) node.IsSelected = true; } } - - /// - /// Event for when the filter on the tree changes - /// - public override void OnFilterChanged() - { - var fullTree = this.RootViewModel?.GetFlatListOfDescendants(true); - - if (fullTree is null) - { - return; - } - - if (this.SelectedFilter == TreeFilter.ShowNodesWithGeometry) - { - fullTree.ForEach(x => - { - x.IsDrawn = x.SceneObject.Primitive != null; - }); - } - else - { - fullTree.ForEach(x => x.IsDrawn = true); - } - } - - /// - /// Event for when the text of the search filter is changing - /// - public override void OnSearchFilterChange() - { - var fullTree = this.RootViewModel?.GetFlatListOfDescendants(true); - - if (this.SearchText == string.Empty) - { - fullTree?.ForEach(x => x.IsDrawn = true); - } - else - { - fullTree?.ForEach(x => { x.IsDrawn = x.Title.Contains(this.SearchText, StringComparison.InvariantCultureIgnoreCase); }); - } - } } }