From 2ec48632699661fb4ebaa5d6196a9e2e06bcc12c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nora=20Emma=20=C2=AB=20Metal-Mighty=20=C2=BB=20Barlow?=
<5247527+Metal-Mighty@users.noreply.github.com>
Date: Mon, 28 Oct 2024 11:30:46 +0100
Subject: [PATCH] #3242 - WIP of in-table filtering and sorting
---
.../Commons/DeviceModelDataGridFilter.razor | 22 +
.../DeviceModelDataGridFilter.razor.cs | 68 +++
.../Concentrators/ConcentratorSearch.razor | 2 +-
.../Devices/DeviceToDuplicateSelector.razor | 4 +-
.../Dialogs/Layer/LinkDeviceLayerDialog.razor | 4 +-
src/IoTHub.Portal.Client/GlobalUsings.cs | 5 +
.../IoTHub.Portal.Client.csproj | 1 +
.../Pages/Devices/DeviceListPage.razor | 544 ++++--------------
.../Pages/Devices/DeviceListPage.razor.cs | 226 ++++++++
.../Pages/Layer/LayerListPage.razor | 2 +-
.../Services/DeviceModelsClientService.cs | 27 +-
.../Validators/ConcentratorValidator.cs | 2 +-
.../Validators/DeviceDetailsValidator.cs | 2 +-
src/IoTHub.Portal.Client/_Imports.razor | 1 +
.../Options/DeviceModelImageOptions.cs | 2 +-
.../Mappers/DeviceTwinMapper.cs | 2 +-
.../Mappers/LoRaDeviceMapper.cs | 2 +-
.../Services/DeviceServiceBase.cs | 2 +-
.../Managers/ExportManager.cs | 7 +-
.../Properties/launchSettings.json | 4 +-
.../Services/DeviceModelService.cs | 30 +-
.../Models/v1.0/DeviceListItem.cs | 2 +-
.../Components/Devices/EditDeviceTests.cs | 6 +-
.../Pages/Devices/DevicesListPageTests.cs | 8 +-
.../Validators/ConcentratorValidatorTests.cs | 2 +-
.../Validators/DeviceDetailValidatorTests.cs | 4 +-
.../Mappers/LoRaDeviceTwinMapperTests.cs | 2 +-
.../Server/Managers/ExportManagerTests.cs | 2 +-
.../Server/Services/DeviceServiceTests.cs | 2 +-
src/IoTHub.Portal.sln | 2 -
30 files changed, 513 insertions(+), 476 deletions(-)
create mode 100644 src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor
create mode 100644 src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor.cs
create mode 100644 src/IoTHub.Portal.Client/GlobalUsings.cs
create mode 100644 src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor.cs
diff --git a/src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor b/src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor
new file mode 100644
index 000000000..0675a1149
--- /dev/null
+++ b/src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor
@@ -0,0 +1,22 @@
+@*
+
+
+ @foreach (var item in @Items)
+ {
+
+
+
+ @item.Name
+
+ }
+
+
+ Filter
+
+
+ *@
diff --git a/src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor.cs b/src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor.cs
new file mode 100644
index 000000000..5482cc861
--- /dev/null
+++ b/src/IoTHub.Portal.Client/Components/Commons/DeviceModelDataGridFilter.razor.cs
@@ -0,0 +1,68 @@
+//// Copyright (c) CGI France. All rights reserved.
+//// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+//namespace IoTHub.Portal.Client.Components.Commons
+//{
+// using Enums;
+// using MudBlazor;
+
+// public partial class DeviceModelDataGridFilter
+// {
+// private bool filterOpen = false;
+// private bool selectAll = true;
+// private HashSet selectedItems = new();
+// private HashSet filterItems = new();
+// private FilterDefinition filterDefinition;
+
+
+// [Parameter] public IEnumerable Items { get; set; }
+
+// //[Parameter] public FilterContext Context {get;}
+
+// protected override Task OnInitializedAsync()
+// {
+// this.selectedItems = Items.ToHashSet();
+// this.filterItems = Items.ToHashSet();
+// this.filterDefinition = new FilterDefinition
+// {
+// FilterFunction = x => this.filterItems.Contains(x)
+// };
+
+// return base.OnInitializedAsync();
+// }
+
+// //private void OpenFilter()
+// //{
+// // this.filterOpen = true;
+// //}
+
+// private void SelectedChanged(bool value, DeviceModelDto item)
+// {
+// _ = value ? this.selectedItems.Add(item) : this.selectedItems.Remove(item);
+
+// this.selectAll = this.selectedItems.Count == Items.Count();
+// }
+
+// //private async Task ApplyFilterAsync(FilterContext context)
+// //{
+// // filterItems = selectedItems.ToHashSet();
+// // //_icon = _filterItems.Count == Items.Count() ? Icons.Material.Outlined.FilterAlt : Icons.Material.Filled.FilterAlt;
+// // await context.Actions.ApplyFilterAsync(filterDefinition);
+// // filterOpen = false;
+// //}
+
+// private void SelectAll(bool value)
+// {
+// selectAll = value;
+
+// if (value)
+// {
+// selectedItems = Items.ToHashSet();
+// }
+// else
+// {
+// selectedItems.Clear();
+// }
+// }
+// }
+//}
diff --git a/src/IoTHub.Portal.Client/Components/Concentrators/ConcentratorSearch.razor b/src/IoTHub.Portal.Client/Components/Concentrators/ConcentratorSearch.razor
index 633db9ded..85fdd3f74 100644
--- a/src/IoTHub.Portal.Client/Components/Concentrators/ConcentratorSearch.razor
+++ b/src/IoTHub.Portal.Client/Components/Concentrators/ConcentratorSearch.razor
@@ -2,7 +2,7 @@
-
+
diff --git a/src/IoTHub.Portal.Client/Components/Devices/DeviceToDuplicateSelector.razor b/src/IoTHub.Portal.Client/Components/Devices/DeviceToDuplicateSelector.razor
index 51f3ac697..8a74707a2 100644
--- a/src/IoTHub.Portal.Client/Components/Devices/DeviceToDuplicateSelector.razor
+++ b/src/IoTHub.Portal.Client/Components/Devices/DeviceToDuplicateSelector.razor
@@ -13,7 +13,7 @@
T="DeviceListItem"
Label="Search a device to duplicate"
SearchFunc="@SearchDevicesToDuplicate"
- ToStringFunc="@(x => x?.DeviceName)"
+ ToStringFunc="@(x => x?.Name)"
DebounceInterval="300"
ValueChanged="OnDeviceSelected"
Dense=true
@@ -23,7 +23,7 @@
Variant="Variant.Outlined"
Required="true">
- @context.DeviceName
+ @context.Name
Id: @context.DeviceID
diff --git a/src/IoTHub.Portal.Client/Dialogs/Layer/LinkDeviceLayerDialog.razor b/src/IoTHub.Portal.Client/Dialogs/Layer/LinkDeviceLayerDialog.razor
index 66b9a1dc6..2bf5da9c3 100644
--- a/src/IoTHub.Portal.Client/Dialogs/Layer/LinkDeviceLayerDialog.razor
+++ b/src/IoTHub.Portal.Client/Dialogs/Layer/LinkDeviceLayerDialog.razor
@@ -46,7 +46,7 @@
- @context.DeviceName
+ @context.Name
@@ -223,7 +223,7 @@
if (device == null) return deviceDetails;
deviceDetails.DeviceID = device.DeviceID;
- deviceDetails.DeviceName = device.DeviceName;
+ deviceDetails.DeviceName = device.Name;
deviceDetails.ModelId = device.DeviceModelId;
deviceDetails.Image = device.Image;
deviceDetails.IsConnected = device.IsConnected;
diff --git a/src/IoTHub.Portal.Client/GlobalUsings.cs b/src/IoTHub.Portal.Client/GlobalUsings.cs
new file mode 100644
index 000000000..46911a4a9
--- /dev/null
+++ b/src/IoTHub.Portal.Client/GlobalUsings.cs
@@ -0,0 +1,5 @@
+// Copyright (c) CGI France. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+global using Microsoft.AspNetCore.Components;
+global using IoTHub.Portal.Models.v10;
diff --git a/src/IoTHub.Portal.Client/IoTHub.Portal.Client.csproj b/src/IoTHub.Portal.Client/IoTHub.Portal.Client.csproj
index 50b7cda91..3c70186c7 100644
--- a/src/IoTHub.Portal.Client/IoTHub.Portal.Client.csproj
+++ b/src/IoTHub.Portal.Client/IoTHub.Portal.Client.csproj
@@ -35,6 +35,7 @@
+
diff --git a/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor b/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor
index a69a278f9..6a6707fbe 100644
--- a/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor
+++ b/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor
@@ -1,138 +1,135 @@
@page "/devices"
-@using IoTHub.Portal
-@using IoTHub.Portal.Models.v10
-@using IoTHub.Portal.Shared.Models.v10;
-@using IoTHub.Portal.Client.Dialogs.Devices
-@using System.Web
-@using System.IO
-@using System.Text.RegularExpressions
-@using System.Net.Http.Headers
-@using IoTHub.Portal.Shared.Models.v10.Filters;
@attribute [Authorize]
@inject IDialogService DialogService
-@inject NavigationManager navigationManager
+@inject NavigationManager NavigationManager
@inject PortalSettings Portal
@inject IDeviceTagSettingsClientService DeviceTagSettingsClientService
@inject IDeviceClientService DeviceClientService
-@inject IJSRuntime JS
+@inject IJSRuntime Js
@inject IDeviceModelsClientService DeviceModelsClientService
-
-
-
-
-
-
- @foreach (DeviceTagDto tag in TagList)
- {
- if (tag.Searchable)
- {
-
-
-
- }
- }
-
-
-
- @foreach (var label in labels)
- {
-
-
-
- }
-
-
-
-
- this.Model)
- Variant="Variant.Outlined"
- ToStringFunc="@(x => x?.Name)"
- ResetValueOnEmptyText=true
- Immediate=true
- Clearable=true
- CoerceText=true
- CoerceValue=false>
-
- @context.Name
-
- @((!string.IsNullOrEmpty(@context.Description) && @context.Description.Length > 100) ? @context.Description.Substring(0, 100) + "..." : @context.Description)
-
-
-
-
-
-
- Status
-
-
- Enabled
-
-
- Disabled
-
-
- All
-
-
-
+
+
+
+
+
+
+
+ @* *@
+
+ @* *@
+
+ @foreach (var item in deviceModels)
+ {
+
+
+
+ @item.Name
+
+ }
+
+
+ Filter
+
+
+
+
+
+
+
+
+ @context.Item.Name
+ @context.Item?.DeviceID
-
- Connection state
-
-
- Connected
-
-
- Disconnected
-
-
- All
-
-
+
+
-
-
-
- Search
- Reset
-
-
-
+
+
+
+
+ @if (context.Item?.IsEnabled != null && (bool)context.Item?.IsEnabled)
+ {
+
+
+
+ }
+ else
+ {
+
+
+
+ }
+
+
+
+
+ @if (context.Item?.IsConnected != null && (bool)context.Item?.IsConnected)
+ {
+
+
+
+ }
+ else
+ {
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
- @if (Portal.IsLoRaSupported)
- {
-
- }
-
-
-
Devices
+
@@ -164,324 +161,19 @@
-
-
-
- Device
- Allowed
- Connection state
- Last status update
- @if (Portal.IsLoRaSupported)
- {
- Telemetry
- }
- See details
- Delete
-
-
-
-
-
-
-
- @context.DeviceName
- @context.DeviceID
-
-
-
-
-
-
-
- @if (context.IsEnabled)
- {
-
-
-
- }
- else
- {
-
-
-
- }
-
-
-
- @if (context.IsConnected)
- {
-
-
-
- }
- else
- {
-
-
-
- }
-
- @context.StatusUpdatedTime
-
- @if (Portal.IsLoRaSupported)
- {
-
- @if (context.HasLoRaTelemetry)
- {
-
-
-
- }
-
- }
-
-
-
-
-
-
-
-
-
-
-
No matching records found
+
Loading...
+
-
+
-
+
-
-@code {
- [CascadingParameter]
- public Error? Error { get; set; }
-
- private string? searchID = "";
- private string? searchStatus;
- private string? searchState;
-
- private MudTable? table;
- private Dictionary searchTags = new();
-
- private bool IsLoading { get; set; } = true;
-
- private DeviceModelDto Model { get; set; } = default!;
-
- private IEnumerable TagList { get; set; } = new List();
-
- private IEnumerable labels = new List();
- private IEnumerable selectedLabels = new List();
-
- private int[] pageSizeOptions = new int[] { 2, 5, 10 };
-
- protected override async Task OnInitializedAsync()
- {
- try
- {
- // Gets the custom tags that can be searched via the panel
- TagList = await DeviceTagSettingsClientService.GetDeviceTags();
- foreach (var tag in TagList)
- {
- if (tag.Searchable)
- searchTags.Add(tag.Name, "");
- }
- labels = await DeviceClientService.GetAvailableLabels();
- }
- catch (ProblemDetailsException exception)
- {
- Error?.ProcessProblemDetails(exception);
- }
- }
-
- private async Task> LoadItems(TableState state)
- {
- try
- {
- string? orderBy = null;
-
- switch (state.SortDirection)
- {
- case SortDirection.Ascending:
- orderBy = $"{state.SortLabel} asc";
- break;
- case SortDirection.Descending:
- orderBy = $"{state.SortLabel} desc";
- break;
- }
-
- var uri = $"api/devices?pageNumber={state.Page}&pageSize={state.PageSize}&searchText={HttpUtility.UrlEncode(searchID)}&searchStatus={searchStatus}&searchState={searchState}&orderBy={orderBy}&modelId={this.Model?.ModelId}";
-
- foreach (var searchTag in searchTags.Where(c => !string.IsNullOrEmpty(c.Value)))
- {
- uri += $"&tag.{searchTag.Key}={searchTag.Value}";
- }
-
- foreach (var label in selectedLabels)
- {
- uri += $"&labels={label.Name}";
- }
-
- var result = await DeviceClientService.GetDevices(uri);
-
- return new TableData
- {
- Items = result.Items,
- TotalItems = result.TotalItems
- };
- }
- catch (ProblemDetailsException exception)
- {
- Error?.ProcessProblemDetails(exception);
-
- return new TableData();
- }
- finally
- {
- IsLoading = false;
- }
- }
-
- private void AddDevice()
- {
- navigationManager.NavigateTo("devices/new");
- }
-
- ///
- /// Reset all the fields in the search panel
- ///
- ///
- private void Reset()
- {
- searchID = "";
- searchStatus = "";
- searchState = "";
- searchTags = searchTags.ToDictionary(tag => tag.Key, tag => "");
- selectedLabels = new List();
-
- Search();
- }
-
- private void Search()
- {
- table?.ReloadServerData();
- }
-
- private void Refresh()
- {
- table?.ReloadServerData();
- }
-
- ///
- /// Prompts a pop-up windows to confirm the device's deletion.
- ///
- /// Device to delete from the hub
- ///
- private async Task DeleteDevice(DeviceListItem device)
- {
- var parameters = new DialogParameters();
- parameters.Add("deviceID", device.DeviceID);
- parameters.Add("deviceName", device.DeviceName);
- parameters.Add("IsLoRaWan", device.SupportLoRaFeatures);
-
- var result = await DialogService.Show("Confirm Deletion", parameters).Result;
-
- if (result.Canceled)
- {
- return;
- }
-
- Search();
- }
-
- private void GoToDetails(DeviceListItem item)
- {
- navigationManager.NavigateTo($"devices/{item.DeviceID}{((item.SupportLoRaFeatures && Portal.IsLoRaSupported) ? "?isLora=true" : "")}");
- }
-
- ///
- /// Allows to autocomplete the Device Model field in the form.
- ///
- /// Text entered in the field
- /// Item of the device model list that matches the user's value
- public async Task> Search(string value)
- {
- var filter = new DeviceModelFilter
- {
- SearchText = value,
- PageNumber = 0,
- PageSize = 10,
- OrderBy = new string[]
- {
- string.Empty
- }
- };
- return (await DeviceModelsClientService.GetDeviceModelsAsync(filter)).Items.ToList();
- }
-
- private async Task ExportDeviceList()
- {
- menuIsOpen = false;
-
- var export = await this.DeviceClientService.ExportDeviceList();
- var fileName = export?.Headers?.ContentDisposition?.Parameters.Single(c => c.Name == "filename").Value;
-
- using var streamRef = new DotNetStreamReference(stream: await (export?.ReadAsStreamAsync())!);
- await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
- }
-
- private async Task ExportTemplateFile()
- {
- menuIsOpen = false;
-
- var export = await this.DeviceClientService.ExportTemplateFile();
- var fileName = export?.Headers?.ContentDisposition?.Parameters.Single(c => c.Name == "filename").Value;
-
- using var streamRef = new DotNetStreamReference(stream: await (export?.ReadAsStreamAsync())!);
- await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
- }
-
- private async Task ShowDeviceTelemetry(DeviceListItem device)
- {
- var parameters = new DialogParameters { { "DeviceID", device.DeviceID } };
- var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true, CloseButton = true };
-
- await DialogService.Show(string.Empty, parameters, options).Result;
- }
-
- private async Task ImportDeviceList(IBrowserFile file)
- {
- menuIsOpen = false;
-
- var fileContent = new StreamContent(file.OpenReadStream());
- fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
-
- var content = new MultipartFormDataContent();
- content.Add(content: fileContent,
- name: "\"file\"",
- fileName: file.Name);
-
- var parameters = new DialogParameters { { "Content", content } };
- var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true, CloseButton = true };
- await DialogService.Show("Import summary", parameters, options).Result;
- }
-
- public bool menuIsOpen;
-
- public void ToggleOpen()
- {
- menuIsOpen = !menuIsOpen;
- }
-
- private string GetMultiSelectionText(List selectedValues)
- {
- return $"{selectedValues.Count} label{(selectedValues.Count > 1 ? "s have" : " has")} been selected";
- }
-}
diff --git a/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor.cs b/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor.cs
new file mode 100644
index 000000000..7e3ea62d8
--- /dev/null
+++ b/src/IoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor.cs
@@ -0,0 +1,226 @@
+namespace IoTHub.Portal.Client.Pages.Devices
+{
+ using System.Collections.Generic;
+ using System.Net.Http.Headers;
+ using System.Web;
+ using Dialogs.Devices;
+ using Exceptions;
+ using Microsoft.AspNetCore.Components;
+ using Microsoft.AspNetCore.Components.Forms;
+ using Microsoft.JSInterop;
+ using MudBlazor;
+ using Portal.Models.v10;
+ using Portal.Shared.Models.v10;
+ using Shared;
+
+ public partial class DeviceListPage
+ {
+ public MudDataGrid devicesGrid = new();
+
+ private bool menuIsOpen;
+ private readonly string searchString = string.Empty;
+ private readonly string? searchStatus = string.Empty;
+ private readonly string? searchState = string.Empty;
+
+ private readonly Dictionary searchTags = new();
+
+ private List deviceModels = new();
+ private readonly List selectedDeviceModels = new();
+
+ private bool IsLoading { get; set; } = true;
+ private List TagList { get; set; } = new();
+ private List labels = new();
+ private readonly List selectedLabels = new();
+ private readonly int[] pageSizeOptions = { 10, 20, 50, 100, int.MaxValue };
+
+ [CascadingParameter] public Error? Error { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ try
+ {
+ // Gets the custom tags that can be searched via the panel
+ TagList = (await DeviceTagSettingsClientService.GetDeviceTags()).ToList();
+ foreach (var tag in TagList.Where(tag => tag.Searchable))
+ this.searchTags.Add(tag.Name, "");
+
+ this.labels = (await DeviceClientService.GetAvailableLabels()).ToList();
+ }
+ catch (ProblemDetailsException exception)
+ {
+ Error?.ProcessProblemDetails(exception);
+ }
+ }
+
+ private async Task> LoadItems(GridState state)
+ {
+ try
+ {
+ var sortByDefinition = state.SortDefinitions.FirstOrDefault();
+ var columnName = this.devicesGrid.RenderedColumns
+ .Find(x => x.PropertyName == sortByDefinition?.SortBy)
+ ?.Title;
+ var propertyName = columnName switch
+ {
+ "Device" => nameof(DeviceListItem.Name),
+ "Allowed" => nameof(DeviceListItem.IsEnabled),
+ "Connection state" => nameof(DeviceListItem.IsConnected),
+ _ => nameof(DeviceListItem.Name)
+ };
+
+ var orderBy = sortByDefinition == null
+ ? "Name asc"
+ : sortByDefinition.Descending switch
+ {
+ false => // ascending
+ $"{propertyName} asc",
+ true => // descending
+ $"{propertyName} desc",
+ };
+
+ var uri = $"api/devices?pageNumber={state.Page}" +
+ $"&pageSize={state.PageSize}" +
+ $"&searchText={HttpUtility.UrlEncode(this.searchString)}" +
+ $"&searchStatus={this.searchStatus}" +
+ $"&searchState={this.searchState}" +
+ $"&orderBy={orderBy}";
+
+ uri = this.selectedDeviceModels.Aggregate(uri,
+ (current, model) => current + $"&modelId={model.ModelId}");
+
+ uri = this.searchTags.Where(c => !string.IsNullOrEmpty(c.Value)).Aggregate(uri,
+ (current, searchTag) => current + $"&tag.{searchTag.Key}={searchTag.Value}");
+
+ uri = this.selectedLabels.Aggregate(uri,
+ (current, label) => current + $"&labels={label.Name}");
+
+ var result = await DeviceClientService.GetDevices(uri);
+ this.deviceModels = await GetDeviceModels();
+
+ return new GridData
+ {
+ Items = result.Items,
+ TotalItems = result.TotalItems
+ };
+ }
+ catch (ProblemDetailsException exception)
+ {
+ Error?.ProcessProblemDetails(exception);
+
+ return new GridData();
+ }
+ finally
+ {
+ IsLoading = false;
+ }
+ }
+
+ private void AddDevice()
+ {
+ NavigationManager.NavigateTo("devices/new");
+ }
+
+ private void Refresh()
+ {
+ _ = this.devicesGrid.ReloadServerData();
+ }
+
+ ///
+ /// Prompts a pop-up windows to confirm the device's deletion.
+ ///
+ /// Device to delete from the hub
+ ///
+ private async Task DeleteDevice(DeviceListItem device)
+ {
+ var parameters = new DialogParameters
+ {
+ { "deviceID", device.DeviceID },
+ { "deviceName", device.Name },
+ { "IsLoRaWan", device.SupportLoRaFeatures }
+ };
+
+ _ = await DialogService.Show("Confirm Deletion", parameters).Result;
+ }
+
+ private void GoToDetails(DeviceListItem item)
+ {
+ NavigationManager.NavigateTo(
+ $"devices/{item.DeviceID}{((item.SupportLoRaFeatures && Portal.IsLoRaSupported) ? "?isLora=true" : "")}");
+ }
+
+ ///
+ /// Allows to autocomplete the Device Model field in the form.
+ ///
+ /// Text entered in the field
+ /// Item of the device model list that matches the user's value
+ public async Task Search()
+ {
+ _ = this.devicesGrid.ReloadServerData();
+ //var filter = new DeviceModelFilter
+ //{
+ // SearchText = value,
+ // PageNumber = 0,
+ // PageSize = 10,
+ // OrderBy = new[] { string.Empty }
+ //};
+ //return (await DeviceModelsClientService.GetDeviceModelsAsync(filter)).Items.ToList();
+ }
+
+ private async Task ExportDeviceList()
+ {
+ this.menuIsOpen = false;
+
+ var export = await DeviceClientService.ExportDeviceList();
+ var fileName = export.Headers.ContentDisposition?.Parameters.Single(c => c.Name == "filename").Value;
+
+ using var streamRef = new DotNetStreamReference(stream: await (export?.ReadAsStreamAsync())!);
+ await Js.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
+ }
+
+ private async Task ExportTemplateFile()
+ {
+ this.menuIsOpen = false;
+
+ var export = await DeviceClientService.ExportTemplateFile();
+ var fileName = export.Headers.ContentDisposition?.Parameters.Single(c => c.Name == "filename").Value;
+
+ using var streamRef = new DotNetStreamReference(stream: await (export?.ReadAsStreamAsync())!);
+ await Js.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
+ }
+
+ private async Task ShowDeviceTelemetry(DeviceListItem device)
+ {
+ var parameters = new DialogParameters { { "DeviceID", device.DeviceID } };
+ var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true, CloseButton = true };
+
+ _ = await (await DialogService.ShowAsync(string.Empty, parameters, options)).Result;
+ }
+
+ private async Task ImportDeviceList(IBrowserFile? file)
+ {
+ this.menuIsOpen = false;
+
+ var fileContent = new StreamContent(file.OpenReadStream());
+ fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
+
+ var content = new MultipartFormDataContent();
+ content.Add(content: fileContent,
+ name: "\"file\"",
+ fileName: file.Name);
+
+ var parameters = new DialogParameters { { "Content", content } };
+ var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true, CloseButton = true };
+ _ = await DialogService.Show("Import summary", parameters, options).Result;
+ }
+
+ private void ToggleOpen()
+ {
+ this.menuIsOpen = !this.menuIsOpen;
+ }
+
+ private async Task> GetDeviceModels()
+ {
+ return (await DeviceModelsClientService.GetDeviceModelsAsync()).Items.ToList();
+ }
+ }
+}
diff --git a/src/IoTHub.Portal.Client/Pages/Layer/LayerListPage.razor b/src/IoTHub.Portal.Client/Pages/Layer/LayerListPage.razor
index 4119b8856..12e6dc77c 100644
--- a/src/IoTHub.Portal.Client/Pages/Layer/LayerListPage.razor
+++ b/src/IoTHub.Portal.Client/Pages/Layer/LayerListPage.razor
@@ -149,7 +149,7 @@
if (device == null) return deviceDetails;
deviceDetails.DeviceID = device.DeviceID;
- deviceDetails.DeviceName = device.DeviceName;
+ deviceDetails.DeviceName = device.Name;
deviceDetails.ModelId = device.DeviceModelId;
deviceDetails.Image = device.Image;
deviceDetails.IsConnected = device.IsConnected;
diff --git a/src/IoTHub.Portal.Client/Services/DeviceModelsClientService.cs b/src/IoTHub.Portal.Client/Services/DeviceModelsClientService.cs
index b047b8264..ffac8237b 100644
--- a/src/IoTHub.Portal.Client/Services/DeviceModelsClientService.cs
+++ b/src/IoTHub.Portal.Client/Services/DeviceModelsClientService.cs
@@ -14,7 +14,7 @@ namespace IoTHub.Portal.Client.Services
public class DeviceModelsClientService : IDeviceModelsClientService
{
private readonly HttpClient http;
- private readonly string apiUrlBase = "api/models";
+ private const string ApiUrlBase = "api/models";
public DeviceModelsClientService(HttpClient http)
{
@@ -23,17 +23,22 @@ public DeviceModelsClientService(HttpClient http)
public async Task> GetDeviceModelsAsync(DeviceModelFilter? deviceModelFilter = null)
{
- var query = new Dictionary
+ var query = new Dictionary();
+ if (deviceModelFilter != null)
{
- { nameof(DeviceModelFilter.SearchText), deviceModelFilter?.SearchText ?? string.Empty },
-#pragma warning disable CA1305
- { nameof(DeviceModelFilter.PageNumber), deviceModelFilter?.PageNumber.ToString() ?? string.Empty },
- { nameof(DeviceModelFilter.PageSize), deviceModelFilter?.PageSize.ToString() ?? string.Empty },
-#pragma warning restore CA1305
- { nameof(DeviceModelFilter.OrderBy), string.Join("", deviceModelFilter?.OrderBy!) ?? string.Empty }
- };
-
- var uri = QueryHelpers.AddQueryString(this.apiUrlBase, query);
+ query = new Dictionary
+ {
+ { nameof(DeviceModelFilter.SearchText), deviceModelFilter?.SearchText ?? string.Empty },
+ { nameof(DeviceModelFilter.PageNumber), deviceModelFilter?.PageNumber.ToString() ?? string.Empty },
+ { nameof(DeviceModelFilter.PageSize), deviceModelFilter?.PageSize.ToString() ?? string.Empty },
+ {
+ nameof(DeviceModelFilter.OrderBy),
+ deviceModelFilter != null ? string.Join("", deviceModelFilter?.OrderBy!) : string.Empty
+ }
+ };
+ }
+
+ var uri = QueryHelpers.AddQueryString(ApiUrlBase, query);
return await this.http.GetFromJsonAsync>(uri) ?? new PaginationResult();
}
diff --git a/src/IoTHub.Portal.Client/Validators/ConcentratorValidator.cs b/src/IoTHub.Portal.Client/Validators/ConcentratorValidator.cs
index cd3735bd9..c19db6594 100644
--- a/src/IoTHub.Portal.Client/Validators/ConcentratorValidator.cs
+++ b/src/IoTHub.Portal.Client/Validators/ConcentratorValidator.cs
@@ -18,7 +18,7 @@ public ConcentratorValidator()
_ = RuleFor(x => x.DeviceName)
.NotEmpty()
- .WithMessage("DeviceName is required.");
+ .WithMessage("Name is required.");
_ = RuleFor(x => x.LoraRegion)
.NotEmpty().WithMessage("LoraRegion is required.")
diff --git a/src/IoTHub.Portal.Client/Validators/DeviceDetailsValidator.cs b/src/IoTHub.Portal.Client/Validators/DeviceDetailsValidator.cs
index f659c24e8..253b93550 100644
--- a/src/IoTHub.Portal.Client/Validators/DeviceDetailsValidator.cs
+++ b/src/IoTHub.Portal.Client/Validators/DeviceDetailsValidator.cs
@@ -17,7 +17,7 @@ public DeviceDetailsValidator(string? cloudProvider = null)
{
_ = RuleFor(x => x.DeviceName)
.NotEmpty()
- .WithMessage("DeviceName is required.");
+ .WithMessage("Name is required.");
_ = RuleFor(x => x.ModelId)
.NotEmpty()
diff --git a/src/IoTHub.Portal.Client/_Imports.razor b/src/IoTHub.Portal.Client/_Imports.razor
index 0725480db..57400ea6a 100644
--- a/src/IoTHub.Portal.Client/_Imports.razor
+++ b/src/IoTHub.Portal.Client/_Imports.razor
@@ -28,5 +28,6 @@
@using IoTHub.Portal.Client.Components.EdgeDevices
@using IoTHub.Portal.Client.Components.EdgeModels
@using IoTHub.Portal.Client.Dialogs.EdgeModels
+@using IoTHub.Portal.Models.v10
@using MudBlazor
@using ChartJs.Blazor;
diff --git a/src/IoTHub.Portal.Domain/Options/DeviceModelImageOptions.cs b/src/IoTHub.Portal.Domain/Options/DeviceModelImageOptions.cs
index fa85f4e31..d40ddd7da 100644
--- a/src/IoTHub.Portal.Domain/Options/DeviceModelImageOptions.cs
+++ b/src/IoTHub.Portal.Domain/Options/DeviceModelImageOptions.cs
@@ -9,7 +9,7 @@ public class DeviceModelImageOptions
{
public Uri BaseUri { get; set; } = default!;
- public const string ImageContainerName = "device-images-2";
+ public const string ImageContainerName = "device-images";
public const string DefaultImageName = "default-template-icon";
diff --git a/src/IoTHub.Portal.Infrastructure/Mappers/DeviceTwinMapper.cs b/src/IoTHub.Portal.Infrastructure/Mappers/DeviceTwinMapper.cs
index d8cfb5acd..1aa3205a7 100644
--- a/src/IoTHub.Portal.Infrastructure/Mappers/DeviceTwinMapper.cs
+++ b/src/IoTHub.Portal.Infrastructure/Mappers/DeviceTwinMapper.cs
@@ -65,7 +65,7 @@ public DeviceListItem CreateDeviceListItem(Twin twin)
IsConnected = twin.ConnectionState == DeviceConnectionState.Connected,
IsEnabled = twin.Status == DeviceStatus.Enabled,
StatusUpdatedTime = twin.StatusUpdatedTime ?? DateTime.MinValue,
- DeviceName = DeviceHelper.RetrieveTagValue(twin, nameof(DeviceListItem.DeviceName)),
+ Name = DeviceHelper.RetrieveTagValue(twin, nameof(DeviceListItem.Name)),
Image = this.deviceModelImageManager.GetDeviceModelImageAsync(DeviceHelper.RetrieveTagValue(twin, nameof(DeviceDetails.ModelId))!).Result,
SupportLoRaFeatures = bool.Parse(DeviceHelper.RetrieveTagValue(twin, nameof(DeviceListItem.SupportLoRaFeatures)) ?? "false")
};
diff --git a/src/IoTHub.Portal.Infrastructure/Mappers/LoRaDeviceMapper.cs b/src/IoTHub.Portal.Infrastructure/Mappers/LoRaDeviceMapper.cs
index 7d2848f66..2eba3ef7d 100644
--- a/src/IoTHub.Portal.Infrastructure/Mappers/LoRaDeviceMapper.cs
+++ b/src/IoTHub.Portal.Infrastructure/Mappers/LoRaDeviceMapper.cs
@@ -151,7 +151,7 @@ public DeviceListItem CreateDeviceListItem(Twin twin)
return new DeviceListItem
{
DeviceID = twin.DeviceId,
- DeviceName = DeviceHelper.RetrieveTagValue(twin, nameof(LoRaDeviceDetails.DeviceName)),
+ Name = DeviceHelper.RetrieveTagValue(twin, nameof(LoRaDeviceDetails.DeviceName)),
Image = this.deviceModelImageManager
.GetDeviceModelImageAsync(DeviceHelper.RetrieveTagValue(twin, nameof(DeviceDetails.ModelId))!)
.Result,
diff --git a/src/IoTHub.Portal.Infrastructure/Services/DeviceServiceBase.cs b/src/IoTHub.Portal.Infrastructure/Services/DeviceServiceBase.cs
index 7a534a112..df80e3c1a 100644
--- a/src/IoTHub.Portal.Infrastructure/Services/DeviceServiceBase.cs
+++ b/src/IoTHub.Portal.Infrastructure/Services/DeviceServiceBase.cs
@@ -121,7 +121,7 @@ public async Task> GetDevices(string searchText
.Select(device => new DeviceListItem
{
DeviceID = device.Id,
- DeviceName = device.Name,
+ Name = device.Name,
IsEnabled = device.IsEnabled,
IsConnected = device.IsConnected,
StatusUpdatedTime = device.StatusUpdatedTime,
diff --git a/src/IoTHub.Portal.Server/Managers/ExportManager.cs b/src/IoTHub.Portal.Server/Managers/ExportManager.cs
index df05c3f67..b7e8ae9aa 100644
--- a/src/IoTHub.Portal.Server/Managers/ExportManager.cs
+++ b/src/IoTHub.Portal.Server/Managers/ExportManager.cs
@@ -22,7 +22,6 @@ namespace IoTHub.Portal.Server.Managers
using CsvHelper;
using CsvHelper.Configuration;
using Microsoft.Extensions.Options;
- using Microsoft.IdentityModel.Tokens;
public class ExportManager : IExportManager
{
@@ -248,7 +247,7 @@ private static Dictionary ReadTags(CsvReader reader, IEnumerable
private static bool TryReadMandatoryFields(CsvReader reader, int lineNumber, ref string deviceId, ref string deviceName, ref string modelId, ref List report)
{
- if (!reader.TryGetField("Id", out deviceId) || deviceId.IsNullOrEmpty())
+ if (!reader.TryGetField("Id", out deviceId) || string.IsNullOrEmpty(deviceId))
{
report.Add(new ImportResultLine
{
@@ -262,7 +261,7 @@ private static bool TryReadMandatoryFields(CsvReader reader, int lineNumber, ref
return false;
}
- if (!reader.TryGetField("Name", out deviceName) || deviceName.IsNullOrEmpty())
+ if (!reader.TryGetField("Name", out deviceName) || string.IsNullOrEmpty(deviceName))
{
report.Add(new ImportResultLine
{
@@ -276,7 +275,7 @@ private static bool TryReadMandatoryFields(CsvReader reader, int lineNumber, ref
return false;
}
- if (!reader.TryGetField("ModelId", out modelId) || modelId.IsNullOrEmpty())
+ if (!reader.TryGetField("ModelId", out modelId) || string.IsNullOrEmpty(modelId))
{
report.Add(new ImportResultLine
{
diff --git a/src/IoTHub.Portal.Server/Properties/launchSettings.json b/src/IoTHub.Portal.Server/Properties/launchSettings.json
index e102b64dc..cd909de95 100644
--- a/src/IoTHub.Portal.Server/Properties/launchSettings.json
+++ b/src/IoTHub.Portal.Server/Properties/launchSettings.json
@@ -18,7 +18,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
- "applicationUrl": "https://localhost:8001;http://localhost:8080",
+ "applicationUrl": "https://localhost:8001;http://localhost:8000",
"dotnetRunMessages": true
},
"WSL": {
@@ -27,7 +27,7 @@
"launchUrl": "https://localhost:8443",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
- "ASPNETCORE_URLS": "https://localhost:8443;http://localhost:8080"
+ "ASPNETCORE_URLS": "https://localhost:8001;http://localhost:8000"
},
"distributionName": ""
}
diff --git a/src/IoTHub.Portal.Server/Services/DeviceModelService.cs b/src/IoTHub.Portal.Server/Services/DeviceModelService.cs
index 88fdb62f7..890dee69f 100644
--- a/src/IoTHub.Portal.Server/Services/DeviceModelService.cs
+++ b/src/IoTHub.Portal.Server/Services/DeviceModelService.cs
@@ -63,16 +63,36 @@ public DeviceModelService(IMapper mapper,
this.externalDeviceService = externalDeviceService;
}
- public async Task> GetDeviceModels(DeviceModelFilter deviceModelFilter)
+ public async Task> GetDeviceModels(DeviceModelFilter? deviceModelFilter)
{
- var deviceModelPredicate = PredicateBuilder.True();
+ var paginatedDeviceModels = new PaginatedResult();
- if (!string.IsNullOrWhiteSpace(deviceModelFilter.SearchText))
+ if (deviceModelFilter == null)
{
- deviceModelPredicate = deviceModelPredicate.And(model => model.Name.ToLower().Contains(deviceModelFilter.SearchText.ToLower()) || model.Description.ToLower().Contains(deviceModelFilter.SearchText.ToLower()));
+ var models = await this.deviceModelRepository.GetAllAsync();
+ paginatedDeviceModels = new PaginatedResult
+ {
+ CurrentPage = 0,
+ Data = models.ToList(),
+ PageSize = models.Count(),
+ TotalCount = models.Count()
+ };
}
+ else
+ {
+ var deviceModelPredicate = PredicateBuilder.True();
- var paginatedDeviceModels = await this.deviceModelRepository.GetPaginatedListAsync(deviceModelFilter.PageNumber, deviceModelFilter.PageSize, deviceModelFilter.OrderBy, deviceModelPredicate, includes: new Expression>[] { d => d.Labels });
+ if (!string.IsNullOrWhiteSpace(deviceModelFilter.SearchText))
+ {
+ deviceModelPredicate = deviceModelPredicate.And(model =>
+ model.Name.ToLower().Contains(deviceModelFilter.SearchText.ToLower()) || model.Description
+ .ToLower().Contains(deviceModelFilter.SearchText.ToLower()));
+ }
+
+ paginatedDeviceModels = await this.deviceModelRepository.GetPaginatedListAsync(
+ deviceModelFilter.PageNumber, deviceModelFilter.PageSize, deviceModelFilter.OrderBy,
+ deviceModelPredicate, includes: new Expression>[] { d => d.Labels });
+ }
var paginateDeviceModelsDto = new PaginatedResult
{
diff --git a/src/IoTHub.Portal.Shared/Models/v1.0/DeviceListItem.cs b/src/IoTHub.Portal.Shared/Models/v1.0/DeviceListItem.cs
index 2a4eb1d3d..32be59140 100644
--- a/src/IoTHub.Portal.Shared/Models/v1.0/DeviceListItem.cs
+++ b/src/IoTHub.Portal.Shared/Models/v1.0/DeviceListItem.cs
@@ -20,7 +20,7 @@ public class DeviceListItem
///
/// The device friendly name.
///
- public string DeviceName { get; set; } = default!;
+ public string Name { get; set; } = default!;
///
/// The device Model Identifier.
diff --git a/src/IoTHub.Portal.Tests.Unit/Client/Components/Devices/EditDeviceTests.cs b/src/IoTHub.Portal.Tests.Unit/Client/Components/Devices/EditDeviceTests.cs
index 8360d1b8a..8c14bb957 100644
--- a/src/IoTHub.Portal.Tests.Unit/Client/Components/Devices/EditDeviceTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Client/Components/Devices/EditDeviceTests.cs
@@ -895,7 +895,7 @@ public void ReturnButtonMustNavigateToPreviousPage()
// var mockDeviceDetails = new DeviceDetails
// {
- // DeviceName = Guid.NewGuid().ToString(),
+ // Name = Guid.NewGuid().ToString(),
// ModelId = mockDeviceModel.ModelId,
// DeviceID = Guid.NewGuid().ToString(),
// Tags = new Dictionary()
@@ -1025,7 +1025,7 @@ public void SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingDev
// var mockDeviceDetails = new DeviceDetails
// {
- // DeviceName = Guid.NewGuid().ToString(),
+ // Name = Guid.NewGuid().ToString(),
// ModelId = mockDeviceModel.ModelId,
// DeviceID = Guid.NewGuid().ToString(),
// Tags = new Dictionary()
@@ -1056,7 +1056,7 @@ public void SaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingDev
// // Act
// var cut = RenderComponent(parameters => parameters.Add(p => p.context, CreateEditMode.Edit).Add(p => p.DeviceID, mockDeviceDetails.DeviceID));
- // cut.WaitForElement($"#{nameof(DeviceDetails.DeviceName)}").Change("");
+ // cut.WaitForElement($"#{nameof(DeviceDetails.Name)}").Change("");
// var saveButton = cut.WaitForElement("#saveButton");
// saveButton.Click();
diff --git a/src/IoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs b/src/IoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs
index 23b443528..75859b04f 100644
--- a/src/IoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Client/Pages/Devices/DevicesListPageTests.cs
@@ -326,12 +326,12 @@ public async Task TypingSomeCharactersInTheAutocompleteShouldFilterTheDeviceMode
new DeviceListItem()
{
DeviceID = Guid.NewGuid().ToString(),
- DeviceName = Guid.NewGuid().ToString(),
+ Name = Guid.NewGuid().ToString(),
},
new DeviceListItem()
{
DeviceID = Guid.NewGuid().ToString(),
- DeviceName = Guid.NewGuid().ToString(),
+ Name = Guid.NewGuid().ToString(),
}
}
});
@@ -363,11 +363,11 @@ public async Task TypingSomeCharactersInTheAutocompleteShouldFilterTheDeviceMode
popoverProvider.WaitForAssertion(() => popoverProvider.FindAll(".mud-input-helper-text").Count.Should().Be(2));
- var newModelList = await cut.Instance.Search("01");
+ await cut.Instance.Search();
// Assert
cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading..."));
- _ = newModelList.Count().Should().Be(2);
+ _ = cut.Instance.devicesGrid.Items.Count().Should().Be(2);
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}
diff --git a/src/IoTHub.Portal.Tests.Unit/Client/Validators/ConcentratorValidatorTests.cs b/src/IoTHub.Portal.Tests.Unit/Client/Validators/ConcentratorValidatorTests.cs
index 95d54ae39..ccba91f73 100644
--- a/src/IoTHub.Portal.Tests.Unit/Client/Validators/ConcentratorValidatorTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Client/Validators/ConcentratorValidatorTests.cs
@@ -30,7 +30,7 @@ public void ValidateValidConcentrator()
Assert.AreEqual(0, concentratorValidation.Errors.Count);
}
- [TestCase("DeviceName", "", "LoraRegionValue")]
+ [TestCase("Name", "", "LoraRegionValue")]
[TestCase("LoraRegion", "DeviceNameValue", "")]
public void ValidateMissingFieldShouldReturnError(
string testedValue,
diff --git a/src/IoTHub.Portal.Tests.Unit/Client/Validators/DeviceDetailValidatorTests.cs b/src/IoTHub.Portal.Tests.Unit/Client/Validators/DeviceDetailValidatorTests.cs
index 7de8b7723..42c82c167 100644
--- a/src/IoTHub.Portal.Tests.Unit/Client/Validators/DeviceDetailValidatorTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Client/Validators/DeviceDetailValidatorTests.cs
@@ -53,7 +53,7 @@ public void ValidateValidAWSDevice()
Assert.AreEqual(0, standardValidation.Errors.Count);
}
- [TestCase("DeviceName", "", "ModelIdValue", "DeviceIDValue")]
+ [TestCase("Name", "", "ModelIdValue", "DeviceIDValue")]
[TestCase("ModelId", "DeviceNameValue", "", "DeviceIDValue")]
[TestCase("DeviceID", "DeviceNameValue", "ModelIdValue", "")]
public void ValidateMissingFieldShouldReturnError(
@@ -80,7 +80,7 @@ public void ValidateMissingFieldShouldReturnError(
Assert.AreEqual(standardValidation.Errors[0].ErrorMessage, $"{testedValue} is required.");
}
- [TestCase("DeviceName", "", "ModelIdValue", "DeviceIDValue")]
+ [TestCase("Name", "", "ModelIdValue", "DeviceIDValue")]
[TestCase("ModelId", "DeviceNameValue", "", "DeviceIDValue")]
public void ValidateMissingAWSFieldShouldReturnError(
string testedValue,
diff --git a/src/IoTHub.Portal.Tests.Unit/Infrastructure/Mappers/LoRaDeviceTwinMapperTests.cs b/src/IoTHub.Portal.Tests.Unit/Infrastructure/Mappers/LoRaDeviceTwinMapperTests.cs
index fa4a6f8bd..b201e73cf 100644
--- a/src/IoTHub.Portal.Tests.Unit/Infrastructure/Mappers/LoRaDeviceTwinMapperTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Infrastructure/Mappers/LoRaDeviceTwinMapperTests.cs
@@ -132,7 +132,7 @@ public void CreateDeviceListItemStateUnderTestExpectedBehavior()
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(twin.DeviceId, result.DeviceID);
- Assert.AreEqual(DeviceHelper.RetrieveTagValue(twin, nameof(LoRaDeviceDetails.DeviceName)), result.DeviceName);
+ Assert.AreEqual(DeviceHelper.RetrieveTagValue(twin, nameof(LoRaDeviceDetails.DeviceName)), result.Name);
Assert.AreEqual(modelImage, result.Image);
diff --git a/src/IoTHub.Portal.Tests.Unit/Server/Managers/ExportManagerTests.cs b/src/IoTHub.Portal.Tests.Unit/Server/Managers/ExportManagerTests.cs
index 97b7b711c..aa7fe7d0a 100644
--- a/src/IoTHub.Portal.Tests.Unit/Server/Managers/ExportManagerTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Server/Managers/ExportManagerTests.cs
@@ -351,7 +351,7 @@ public async Task ImportDeviceListCorrectFileMissingMandatoryFieldShouldDisplayE
_ = textContent.AppendLine("Id,Name,ModelId,TAG:supportLoRaFeatures,TAG:Tag1,TAG:Tag2,PROPERTY:Property1,PROPERTY:Property2,PROPERTY:AppKey,PROPERTY:AppEUI,PROPERTY:AppSKey,PROPERTY:NwkSKey,PROPERTY:DevAddr,PROPERTY:GatewayID,PROPERTY:Downlink,PROPERTY:ClassType,PROPERTY:PreferredWindow,PROPERTY:Deduplication,PROPERTY:RX1DROffset,PROPERTY:RX2DataRate,PROPERTY:RXDelay,PROPERTY:ABPRelaxMode,PROPERTY:SensorDecoder,PROPERTY:FCntUpStart,PROPERTY:FCntDownStart,PROPERTY:FCntResetCounter,PROPERTY:Supports32BitFCnt,PROPERTY:KeepAliveTimeout");
// Missing DeviceId
_ = textContent.AppendLine(",ImportLoRa,dc1f171b-8e51-4c6d-a1c6-942b4a0f995b,true,Tag1-Value1,Tag2-Value1,,,AppKeyValue,AppEUIValue,,,,,true,C,1,Drop,,,1,,http://sensor-decoder-url/test,,,,,1");
- // Missing DeviceName
+ // Missing Name
_ = textContent.AppendLine("0000000000000002,,f8b7a67a-345d-463e-ae0e-eeb0f6d24e38,false,Tag1-Value2,Tag2-Value2,Property1Value,Property1Value,,,,,,,,,,,,,,,,,,,,");
// Missing ModelId
_ = textContent.AppendLine("0000000000000003,ImportNonLoRa,,false,Tag1-Value3,Tag2-Value3,Property1Value,Property1Value,,,,,,,,,,,,,,,,,,,,");
diff --git a/src/IoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs b/src/IoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs
index 5e6474ebd..56706194d 100644
--- a/src/IoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs
+++ b/src/IoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs
@@ -195,7 +195,7 @@ public async Task GetDevices_CustomFilter_ReturnsExpectedDevices()
_ = result.TotalCount.Should().Be(expectedTotalDevicesCount);
_ = result.PageSize.Should().Be(expectedPageSize);
_ = result.CurrentPage.Should().Be(expectedCurrentPage);
- _ = result.Data[0].DeviceName.Should().Be(device1.Name);
+ _ = result.Data[0].Name.Should().Be(device1.Name);
MockRepository.VerifyAll();
}
diff --git a/src/IoTHub.Portal.sln b/src/IoTHub.Portal.sln
index fd250ee6d..1aaf4ca15 100644
--- a/src/IoTHub.Portal.sln
+++ b/src/IoTHub.Portal.sln
@@ -95,9 +95,7 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B9D2DE01-84DE-461F-998C-20B57E4AA021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B9D2DE01-84DE-461F-998C-20B57E4AA021}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9D2DE01-84DE-461F-998C-20B57E4AA021}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B9D2DE01-84DE-461F-998C-20B57E4AA021}.Release|Any CPU.Build.0 = Release|Any CPU
{EF219BC4-0C53-4DE7-92D1-F970C6E56E71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF219BC4-0C53-4DE7-92D1-F970C6E56E71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF219BC4-0C53-4DE7-92D1-F970C6E56E71}.Release|Any CPU.ActiveCfg = Release|Any CPU