Skip to content

Commit

Permalink
Finish implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander van Delft committed Dec 13, 2024
1 parent 815b0a2 commit afb39c9
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 77 deletions.
65 changes: 63 additions & 2 deletions COMET.Web.Common/Components/CardView/CardField.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CardField.cs" company="Starion Group S.A.">
// Copyright (c) 2023-2024 Starion Group S.A.
//
// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine, Nabil Abbar
//
// 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.
//
// 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.
//
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace COMET.Web.Common.Components.CardView
{
using System.Text.RegularExpressions;
Expand All @@ -8,39 +32,76 @@ namespace COMET.Web.Common.Components.CardView
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

/// <summary>
/// A component that represents a data field in a <see cref="CardView{T}"/>'s ItemTemplate
/// </summary>
/// <typeparam name="T"></typeparam>
public class CardField<T> : ComponentBase
{
/// <summary>
/// The <see cref="TypeAccessor"/> used to read properties from the instance of <see cref="T"/>.

Check warning on line 42 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 42 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 42 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 42 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 42 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 42 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter
/// This is a static property on a generic type, so it will have different static values for each used generic type in the application
/// </summary>
private static TypeAccessor typeAccessor { get; set; }

/// <summary>
/// Initializes the static properties of this <see cref="CardField{T}"/> class
/// </summary>
static CardField()
{
typeAccessor = TypeAccessor.Create(typeof(T));
}

/// <summary>
/// Gets or sets The parent <see cref="CardView{T}"/>t
/// </summary>
[CascadingParameter(Name="CardView")]
private CardView<T> CardView { get; set; }

/// <summary>
/// The SearchTerm of the <see cref="CardView{T}"/> used to visually show the SearchTerm in this <see cref="CardField{T}"/>
/// </summary>
[CascadingParameter(Name = "SearchTerm")]
private string SearchTerm { get; set; }

/// <summary>
/// Gets or sets the context of this <see cref="CardField{T}"/>
/// </summary>
[Parameter]
public T Context { get; set; }

/// <summary>
/// Gets or sets the FieldName (propertyname of <see cref="T"/>) to show in the UI

Check warning on line 74 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 74 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 74 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 74 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 74 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 74 in COMET.Web.Common/Components/CardView/CardField.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter
/// </summary>
[Parameter]
public string FieldName { get; set; }

/// <summary>
/// Gets or sets a value indicating that sorting is allowed for this <see cref="CardField{T}"/>
/// </summary>
[Parameter]
public bool AllowSort { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating that searching is allowed for this <see cref="CardField{T}"/>
/// </summary>
[Parameter]
public bool AllowSearch { get; set; } = true;

/// <summary>
/// Method invoked when the component is ready to start, having received its
/// initial parameters from its parent in the render tree.
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
this.CardView.RegisterCardField(this);
this.CardView.InitializeCardField(this);
}

/// <summary>
/// Renders the component to the supplied <see cref="RenderTreeBuilder"/>.
/// </summary>
/// <param name="builder">A <see cref="RenderTreeBuilder"/> that will receive the render output.</param>
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
Expand Down
21 changes: 13 additions & 8 deletions COMET.Web.Common/Components/CardView/CardView.razor
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,29 @@
@typeparam T
@inherits DisposableComponent

<p style="visibility:@(this.AllowSearch ? "block": "hidden");">
<p>
<table>
<tr>
<td><input type="text" @oninput="this.OnSearchTextChanged" placeholder="Search..."/></td>
<td><DxComboBox Data="@this.SortFields" SelectedItemChanged="@((string x) => this.OnSelectedItemChanged(x))"
@bind-Value="@this.SelectedSortField"/>
<td style="visibility:@(this.AllowSearch ? "block": "hidden");">
<DxTextBox CssClass="inline-search-icon" SizeMode="SizeMode.Medium" BindValueMode="BindValueMode.OnDelayedInput" InputDelay="500" TextChanged="@((string x) => this.OnSearchTextChanged(x))" NullText="Search..." ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
</DxTextBox>
</td>
<td style="visibility:@(this.AllowSort ? "block": "hidden");">
<DxComboBox CssClass="inline-sort-icon" FilteringMode="DataGridFilteringMode.Contains" SizeMode="SizeMode.Medium" Data="@this.SortFields" SelectedItemChanged="@((string x) => this.OnSelectedSortItemChanged(x))"
@bind-Value="@this.selectedSortField">
</DxComboBox>
</td>
</tr>
</table>
</p>
<div class="container" style="height:calc(100% - 30px); overflow:auto;">
<div class="container" style="height:calc(100% - 40px); overflow:auto;">
<div class="row">
<Virtualize ItemSize="@this.ItemSize" ItemsProvider="this.LoadItems" @ref="this.virtualize">
<ItemContent>
<div class="col" style="height:(@this.ItemSize)px;min-width:(@this.MinWidth)px;">
<div class="col" style="padding-left:0px;margin-left:0px;height:(@this.ItemSize)px;min-width:(@this.MinWidth)px;">
<div class="card @(this.GetSelectedClass(@context))"
@onclick="@(() => this.selectOption(@context))"
draggable="true"
@onclick="@(() => this.selectItem(@context))"
draggable="false"
dropzone="move"
ondragover="event.preventDefault();"
@ondragstart="@(() => this.OnDragNode(@context))"
Expand Down
122 changes: 75 additions & 47 deletions COMET.Web.Common/Components/CardView/CardView.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ namespace COMET.Web.Common.Components
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web.Virtualization;

using System.Linq.Dynamic;
using System.Linq.Dynamic.Core;

/// <summary>
Expand All @@ -52,6 +51,18 @@ public partial class CardView<T> : DisposableComponent
[Parameter]
public ICollection<T> Items { get; set; } = new List<T>();

/// <summary>
/// Gets or sets the fixed height of a Card, used to calculate the amout of items to load into the DOM in px
/// </summary>
[Parameter]
public float ItemSize { get; set; } = 150;

/// <summary>
/// Gets or sets the minimum width of a Card
/// </summary>
[Parameter]
public float MinWidth { get; set; } = 250;

/// <summary>
/// Gets or sets a collection of propertynames of type <see cref="T"/> to perform search on

Check warning on line 67 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 67 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 67 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 67 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 67 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 67 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter
/// </summary>
Expand All @@ -63,21 +74,21 @@ public partial class CardView<T> : DisposableComponent
public SortedSet<string> SortFields { get; set; } = [string.Empty];

/// <summary>
/// Gets or sets the fixed height of a Card, used to calculate the amout of items to load into the DOM in px
/// Gets or sets a value indication that sorting is allowed
/// </summary>
[Parameter]
public float ItemSize { get; set; } = 150;
public bool AllowSort { get; set; } = false;

/// <summary>
/// Gets or sets the minimum width of a Card
/// Gets or sets a value indication that searching is allowed
/// </summary>
[Parameter]
public float MinWidth { get; set; } = 250;

public bool AllowSort { get; set; } = false;

public bool AllowSearch { get; set; } = false;

/// <summary>
/// hold a reference to the previously selected Item.
/// Typically used to check for changes in Items collection
/// </summary>
private ICollection<T> previousItems = null;

/// <summary>
/// A reference to the <see cref="Virtualize{T}"/> component for loading items
/// </summary>
Expand All @@ -99,17 +110,20 @@ public partial class CardView<T> : DisposableComponent
private T draggedNode { get; set; }

/// <summary>
/// Gets or sets the term where to search/filter item of
/// Gets or sets the term where to search/filter items on
/// </summary>
private string searchTerm { get; set; } = string.Empty;

public string SelectedSortField { get; set; }
/// <summary>
/// Gets or sets the term where to sort items on
/// </summary>
private string selectedSortField { get; set; } = string.Empty;

/// <summary>
/// Gets the class to visually show a Card to be selected or unselected
/// </summary>
/// <param name="vm"></param>
/// <returns></returns>
/// <returns>A string that retrurns the css class for selected Card</returns>
private string GetSelectedClass(T vm)
{
return vm.Equals(this.selected) ? "selected" : "";
Expand All @@ -118,8 +132,8 @@ private string GetSelectedClass(T vm)
/// <summary>
/// Set the selected item
/// </summary>
/// <param name="item"></param>
private void selectOption(T item)
/// <param name="item">The item <see cref="T"/></param>

Check warning on line 135 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 135 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 135 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 135 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 135 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter

Check warning on line 135 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

XML comment has cref attribute 'T' that refers to a type parameter
private void selectItem(T item)
{
this.selected = item;
}
Expand All @@ -140,18 +154,7 @@ private void OnDragNode(T node)
/// <returns>A <see cref="Task"/></returns>
private async Task OnDropNode(T targetNode)

Check warning on line 155 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 155 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 155 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 155 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 155 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 155 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
//TODO: Implement
// var targetFolder = (Folder)targetNode.Thing;

// switch (this.DraggedNode?.Thing)
// {
// case File file:
// await this.ViewModel.FileHandlerViewModel.MoveFile(file, targetFolder);
// break;
// case Folder folder:
// await this.ViewModel.FolderHandlerViewModel.MoveFolder(folder, targetFolder);
// break;
// }
//not implemented yet
}

/// <summary>
Expand All @@ -162,16 +165,16 @@ private async Task OnDropNode(T targetNode)
private async ValueTask<ItemsProviderResult<T>> LoadItems(ItemsProviderRequest request)

Check warning on line 165 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 165 in COMET.Web.Common/Components/CardView/CardView.razor.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
// Filter items based on the SearchTerm
var filteredItems = string.IsNullOrWhiteSpace(this.searchTerm)
var filteredItems = !this.AllowSearch || string.IsNullOrWhiteSpace(this.searchTerm)
? this.Items
: this.Items.Where(item => this.FilterItem(item, this.searchTerm)).ToList();

// Return paged items for virtualization
var items = filteredItems.Skip(request.StartIndex).Take(request.Count);

if (!string.IsNullOrWhiteSpace(this.SelectedSortField))
if (this.AllowSort && !string.IsNullOrWhiteSpace(this.selectedSortField))
{
items = items.AsQueryable().OrderBy(this.SelectedSortField);
items = items.AsQueryable().OrderBy(this.selectedSortField);
}

return new ItemsProviderResult<T>(items.ToList(), filteredItems.Count);
Expand All @@ -185,31 +188,36 @@ private async ValueTask<ItemsProviderResult<T>> LoadItems(ItemsProviderRequest r
/// <returns>True if the item's selected properties contain the value to search for, otherwise false</returns>
private bool FilterItem(T item, string query)
{
var props = this.typeAccessor.GetMembers();

return props.Where(x => this.SearchFields.Contains(x.Name)).Any(prop =>
if (this.AllowSearch)
{
var value = this.typeAccessor[item, prop.Name].ToString();
return value != null && value.Contains(query, StringComparison.OrdinalIgnoreCase);
});
var props = this.typeAccessor.GetMembers();

return props.Where(x => this.SearchFields.Contains(x.Name)).Any(prop =>
{
var value = this.typeAccessor[item, prop.Name].ToString();
return value != null && value.Contains(query, StringComparison.OrdinalIgnoreCase);
});
}

return true;
}

/// <summary>
/// A method that is executed when the user changes the search input element
/// </summary>
/// <param name="e">The <see cref="ChangeEventArgs"/> from the UI element's event</param>
/// <returns></returns>
private async Task OnSearchTextChanged(ChangeEventArgs e)
/// <param name="value">The text from the UI element's event</param>
private void OnSearchTextChanged(string value)
{
this.searchTerm = e.Value?.ToString() ?? string.Empty;
this.searchTerm = value ?? string.Empty;

if (this.virtualize != null)
{
await this.virtualize.RefreshDataAsync(); // Tell Virtualize to refresh data
}
this.virtualize?.RefreshDataAsync(); // Tell Virtualize to refresh data
}

internal void RegisterCardField(CardField<T> cardField)
/// <summary>
/// Initializes the <see cref="CardField{T}"/>
/// </summary>
/// <param name="cardField">the <see cref="CardField{T}"/></param>
internal void InitializeCardField(CardField<T> cardField)
{
if (cardField.AllowSort)
{
Expand All @@ -230,11 +238,31 @@ internal void RegisterCardField(CardField<T> cardField)
}
}

private void OnSelectedItemChanged(string arg)
/// <summary>
/// Handles the selection of a the Sort item
/// </summary>
/// <param name="arg"></param>
private void OnSelectedSortItemChanged(string arg)
{
this.SelectedSortField = arg ?? string.Empty;
this.selectedSortField = arg ?? string.Empty;

this.virtualize?.RefreshDataAsync(); // Tell Virtualize to refresh data
}

/// <summary>
/// Raised when a parameter is set
/// </summary>
/// <returns>An awaitable <see cref="Task"/></returns>
protected override async Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();

if (!Equals(this.previousItems, this.Items) && this.virtualize != null)
{
await this.virtualize.RefreshDataAsync(); // Tell Virtualize to refresh data
}

this.previousItems = this.Items;
}
}
}
Loading

0 comments on commit afb39c9

Please sign in to comment.