diff --git a/src/AzureIoTHub.Portal.Client/Components/Devices/EditDevice.razor b/src/AzureIoTHub.Portal.Client/Components/Devices/EditDevice.razor
index 1ba801cc9..f63ed6d21 100644
--- a/src/AzureIoTHub.Portal.Client/Components/Devices/EditDevice.razor
+++ b/src/AzureIoTHub.Portal.Client/Components/Devices/EditDevice.razor
@@ -38,7 +38,9 @@
-
+
+
+
@if (context.Equals(CreateEditMode.Edit))
@@ -99,18 +101,18 @@
{
this.DeviceModel)
- Variant="Variant.Outlined"
- ToStringFunc="@(x => x?.Name)"
- ResetValueOnEmptyText=true
- Immediate=true
- Clearable=true
- CoerceText=true
- CoerceValue=false>
+ @bind-Value="DeviceModel"
+ SearchFunc="@Search"
+ Label="Model*"
+ Dense=true
+ For=@(() => this.DeviceModel)
+ Variant="Variant.Outlined"
+ ToStringFunc="@(x => x?.Name)"
+ ResetValueOnEmptyText=true
+ Immediate=true
+ Clearable=true
+ CoerceText=true
+ CoerceValue=false>
@context.Name
@@ -133,22 +135,22 @@
{
+ Label="Device ID / DevEUI"
+ Variant="Variant.Outlined"
+ Validation=@(loraValidator.ValidateValue)
+ For="@(()=> Device.DeviceID)"
+ Mask="@maskLoRaDeviceID"
+ HelperText="Device EUI must contain 16 hexadecimal characters (numbers from 0 to 9 and/or letters from A to F)" />
}
else
{
+ Label="Device ID"
+ Variant="Variant.Outlined"
+ Validation=@(standardValidator.ValidateValue)
+ For="@(()=> Device.DeviceID)"
+ HelperText="The device identifier should be of ASCII 7-bit alphanumeric characters plus certain special characters" />
}
}
@@ -157,12 +159,12 @@
+ Label="Device ID"
+ Variant="Variant.Outlined"
+ For="@(()=> Device.DeviceID)"
+ Required="true"
+ ReadOnly="true"
+ HelperText="DeviceID must contain 16 hexadecimal characters (numbers from 0 to 9 and/or letters from A to F)" />
}
@@ -214,8 +216,8 @@
{
+ Required="@tag.Required"
+ Variant="Variant.Outlined" />
}
else if (context.Equals(CreateEditMode.Edit))
@@ -226,8 +228,8 @@
Device.Tags.Add(tag.Name, "");
}
+ Required="@tag.Required"
+ Variant="Variant.Outlined" />
}
}
@@ -277,37 +279,37 @@
case DevicePropertyType.Double:
string.IsNullOrEmpty(c) || double.TryParse(c, out var result))
- Clearable="true" />
+ Label="@item.DisplayName"
+ Variant="Variant.Outlined"
+ Validation=@((string c) => string.IsNullOrEmpty(c) || double.TryParse(c, out var result))
+ Clearable="true" />
break;
case DevicePropertyType.Float:
string.IsNullOrEmpty(c) || float.TryParse(c, out var result))
- Clearable="true" />
+ Label="@item.DisplayName"
+ Variant="Variant.Outlined"
+ Validation=@((string c) => string.IsNullOrEmpty(c) || float.TryParse(c, out var result))
+ Clearable="true" />
break;
case DevicePropertyType.Integer:
string.IsNullOrEmpty(c) || int.TryParse(c, out var result))
- Clearable="true" />
+ Label="@item.DisplayName"
+ Variant="Variant.Outlined"
+ Validation=@((string c) => string.IsNullOrEmpty(c) || int.TryParse(c, out var result))
+ Clearable="true" />
break;
case DevicePropertyType.Long:
string.IsNullOrEmpty(c) || long.TryParse(c, out var result))
- Clearable="true" />
+ Label="@item.DisplayName"
+ Variant="Variant.Outlined"
+ Validation=@((string c) => string.IsNullOrEmpty(c) || long.TryParse(c, out var result))
+ Clearable="true" />
break;
case DevicePropertyType.String:
@@ -712,9 +714,9 @@
PageNumber = 0,
PageSize = 100,
OrderBy = new string[]
- {
+ {
string.Empty
- }
+ }
};
return (await DeviceModelsClientService.GetDeviceModels(filter)).Items.ToList();
}
diff --git a/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/CreateDeviceModelPage.razor b/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/CreateDeviceModelPage.razor
index ca55dead3..731ef9696 100644
--- a/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/CreateDeviceModelPage.razor
+++ b/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/CreateDeviceModelPage.razor
@@ -22,7 +22,9 @@
-
+
+
+
@@ -94,35 +96,35 @@
+ @bind-Value="@item.DisplayName"
+ Label="Display name"
+ Variant="Variant.Outlined"
+ For="@(()=> item.DisplayName)"
+ Required="true" />
+ Label="Name"
+ Variant="Variant.Outlined"
+ For="@(()=> item.Name)"
+ Required="true" />
+ @bind-Value="@item.Order"
+ Label="Order"
+ Variant="Variant.Outlined"
+ Min=0
+ For="@(()=> item.Order)"
+ Required="true" />
+ @bind-Value="@item.PropertyType"
+ Label="Type"
+ Variant="Variant.Outlined"
+ For="@(()=> item.PropertyType)"
+ Required="true">
@foreach (DevicePropertyType item in Enum.GetValues(typeof(DevicePropertyType)))
{
@item
@@ -163,7 +165,7 @@
{
+ Commands="Commands" />
}
diff --git a/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/DeviceModelDetailPage.razor b/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/DeviceModelDetailPage.razor
index 3814afd4c..42694ae3c 100644
--- a/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/DeviceModelDetailPage.razor
+++ b/src/AzureIoTHub.Portal.Client/Pages/DeviceModels/DeviceModelDetailPage.razor
@@ -15,10 +15,10 @@
@inject ILoRaWanDeviceModelsClientService LoRaWanDeviceModelsClientService
-
+
- Device Model
+ Device Model
@@ -27,7 +27,9 @@
-
+
+
+
@@ -84,49 +86,49 @@
+ @bind-Value="@item.DisplayName"
+ Label="Display name"
+ Variant="Variant.Outlined"
+ For="@(()=> item.DisplayName)"
+ Required="true" />
+ Label="Name"
+ Variant="Variant.Outlined"
+ For="@(()=> item.Name)"
+ Required="true" />
+ @bind-Value="@item.Order"
+ Label="Order"
+ Variant="Variant.Outlined"
+ Min=0
+ For="@(()=> item.Order)"
+ Required="true" />
+ @bind-Value="@item.PropertyType"
+ Label="Type"
+ Variant="Variant.Outlined"
+ For="@(()=> item.PropertyType)"
+ Required="true">
@foreach (DevicePropertyType item in Enum.GetValues(typeof(DevicePropertyType)))
{
- @item
+ @item
}
-
-
-
-
- Writable
-
-
- Remove
-
-
+
+
+
+
+ Writable
+
+
+ Remove
+
+
}
@@ -152,7 +154,7 @@
{
+ Commands="Commands" />
}
@@ -319,7 +321,7 @@
}
// Check validation error in commands
- foreach(var cmd in Commands)
+ foreach (var cmd in Commands)
{
if (!CommandValidator.Validate(cmd).IsValid)
cmdValidationError = true;
@@ -382,7 +384,7 @@
{
isProcessing = false;
}
-
+
}
private async Task DeleteDeviceModel()
@@ -406,4 +408,4 @@
// Go back to the list of devices after the deletion
NavigationManager.NavigateTo("device-models");
}
- }
+}
diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor
index bfe6c2051..9b9e71c1d 100644
--- a/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor
+++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/CreateEdgeDevicePage.razor
@@ -25,7 +25,9 @@
-
+
+
+
@@ -51,26 +53,26 @@
- @if (duplicateDevice)
+ @if (duplicateDevice)
{
}
else
{
this.edgeModel)
- Variant="Variant.Outlined"
- ToStringFunc="@(x => x?.Name)"
- ResetValueOnEmptyText=true
- Immediate=true
- Clearable=true
- CoerceText=true
- CoerceValue=false>
+ id="@nameof(IoTEdgeModel.ModelId)"
+ @bind-Value="edgeModel"
+ SearchFunc="@Search"
+ Label="Model*"
+ Dense=true
+ For=@(() => this.edgeModel)
+ Variant="Variant.Outlined"
+ ToStringFunc="@(x => x?.Name)"
+ ResetValueOnEmptyText=true
+ Immediate=true
+ Clearable=true
+ CoerceText=true
+ CoerceValue=false>
@context.Name
@@ -86,7 +88,7 @@
-
+ Required="@tag.Required"
+ Variant="Variant.Outlined" />
}
@@ -154,7 +156,7 @@
-
+
@@ -306,18 +308,18 @@
if (string.IsNullOrEmpty(value))
return edgeModelList
.Select(m => new IoTEdgeModel
- {
- ModelId = m.ModelId,
- Name = m.Name
- });;
+ {
+ ModelId = m.ModelId,
+ Name = m.Name
+ }); ;
return edgeModelList
.Where(x => x.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase))
.Select(m => new IoTEdgeModel
- {
- ModelId = m.ModelId,
- Name = m.Name
- });
+ {
+ ModelId = m.ModelId,
+ Name = m.Name
+ });
}
internal async Task ChangeModel(IoTEdgeModel edgeModel)
diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor
index 7f9e17d5f..f8c3f77eb 100644
--- a/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor
+++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceDetailPage.razor
@@ -13,10 +13,10 @@
@inject IDeviceTagSettingsClientService DeviceTagSettingsClientService
-
+
- Edge Device Details
+ Edge Device Details
@@ -27,15 +27,17 @@
Model: @edgeModel.Name
@(string.IsNullOrEmpty(edgeDevice.DeviceName) ? edgeDevice.DeviceId : edgeDevice.DeviceName)
-
-
-
-
-
-
-
-
- @if (isLoaded)
+
+
+
+
+
+
+
+
+
+
+ @if (isLoaded)
{
Connect
}
@@ -121,22 +123,23 @@
-
+
Last deployment
- @if (edgeDevice.LastDeployment != null){
-
-
-
-
-
-
-
-
-
-
-
- }
+ @if (edgeDevice.LastDeployment != null)
+ {
+
+
+
+
+
+
+
+
+
+
+
+ }
@@ -188,8 +191,8 @@
edgeDevice.Tags.Add(tag.Name, "");
}
+ Required="@tag.Required"
+ Variant="Variant.Outlined" />
}
@@ -387,16 +390,16 @@
public async Task ShowConnectionString()
{
- var parameters = new DialogParameters {{nameof(ConnectionStringDialog.deviceId), this.deviceId}};
+ var parameters = new DialogParameters { { nameof(ConnectionStringDialog.deviceId), this.deviceId } };
- _ = await DialogService.Show("Edge Device Connection String", parameters).Result;
+ _ = await DialogService.Show("Edge Device Connection String", parameters).Result;
}
public async Task ShowDeleteModal()
{
isProcessing = true;
- var parameter = new DialogParameters {{nameof(edgeDevice.DeviceId), edgeDevice.DeviceId}};
+ var parameter = new DialogParameters { { nameof(edgeDevice.DeviceId), edgeDevice.DeviceId } };
var result = await DialogService.Show("Edge device deletion confirmation", parameter).Result;
diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor
index 0fba80663..10cc8c650 100644
--- a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor
+++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor
@@ -21,7 +21,9 @@
-
+
+
+
diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor
index 1d199a89d..eea4b846c 100644
--- a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor
+++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor
@@ -27,7 +27,9 @@
-
+
+
+
diff --git a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeDevice.cs b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeDevice.cs
index f2326e5d1..448abefbd 100644
--- a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeDevice.cs
+++ b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeDevice.cs
@@ -69,7 +69,7 @@ public class IoTEdgeDevice
///
/// The IoT Edge configuraton.
///
- public ConfigItem LastDeployment { get; set; } = new ConfigItem();
+ public ConfigItem LastDeployment { get; set; }
///
/// The IoT Edge modules.
diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs
index ac771f91f..29d07c8f7 100644
--- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs
+++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/CreateEdgeDevicePageTest.cs
@@ -342,7 +342,7 @@ public async Task ChangeEdgeModelShouldDisplayModelImage()
await cut.Instance.ChangeModel(edgeModel);
// Assert
- Assert.IsFalse(string.IsNullOrEmpty(ModelImageElement.InnerHtml));
+ Assert.AreEqual(edgeModel.ImageUrl, ModelImageElement.Attributes["src"].Value);
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}
diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs
index 6788d4ad8..586f1174d 100644
--- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs
+++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceDetailPageTests.cs
@@ -21,6 +21,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Client.Pages.EdgeDevices
using MudBlazor.Services;
using NUnit.Framework;
using UnitTests.Mocks;
+ using AutoFixture;
[TestFixture]
public class EdgeDeviceDetailPageTests : BlazorUnitTest
@@ -358,6 +359,43 @@ public void EdgeDeviceDetailPageShouldProcessProblemDetailsExceptionWhenIssueOcc
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}
+ [Test]
+ public void EdgeDeviceDetailPageShouldDisplayLastDeploymentStatus()
+ {
+ // Arrange
+ var mockIoTEdgeModule = new IoTEdgeModule()
+ {
+ ModuleName = Guid.NewGuid().ToString()
+ };
+
+ var mockIoTEdgeDevice = new IoTEdgeDevice()
+ {
+ DeviceId = this.mockdeviceId,
+ ConnectionState = "Connected",
+ Modules= new List(){mockIoTEdgeModule},
+ ModelId = Guid.NewGuid().ToString(),
+ LastDeployment = Fixture.Create()
+ };
+
+ _ = this.mockEdgeDeviceClientService.Setup(service => service.GetDevice(this.mockdeviceId))
+ .ReturnsAsync(mockIoTEdgeDevice);
+
+ _ = this.mockIEdgeModelClientService
+ .Setup(service => service.GetIoTEdgeModel(It.Is(x => x.Equals(mockIoTEdgeDevice.ModelId, StringComparison.Ordinal))))
+ .ReturnsAsync(new IoTEdgeModel());
+
+ _ = this.mockDeviceTagSettingsClientService.Setup(service => service.GetDeviceTags()).ReturnsAsync(new List());
+
+ // Act
+ var cut = RenderComponent(ComponentParameter.CreateParameter("deviceId", this.mockdeviceId));
+
+ // Assert
+ cut.WaitForAssertion(() => Assert.AreEqual(mockIoTEdgeDevice.LastDeployment.Name, cut.WaitForElement("#lastDeploymentName").GetAttribute("value")));
+ cut.WaitForAssertion(() => Assert.AreEqual(mockIoTEdgeDevice.LastDeployment.DateCreation.Date, DateTime.TryParse(cut.WaitForElement("#lastDeploymentDate").GetAttribute("value"), out var dateTime) ? dateTime : null));
+ cut.WaitForAssertion(() => Assert.AreEqual(mockIoTEdgeDevice.LastDeployment.Status, cut.WaitForElement("#lastDeploymentStatus").GetAttribute("value")));
+ cut.WaitForAssertion(() => MockRepository.VerifyAll());
+ }
+
[Test]
public void ClickOnLogsShouldDisplayLogs()
{
diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs
index 5bbdc22c9..929428907 100644
--- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs
+++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs
@@ -359,7 +359,7 @@ public void DeleteAvatarShouldRemoveTheImage()
// Act
var cut = RenderComponent(ComponentParameter.CreateParameter("ModelID", this.mockEdgeModleId));
- cut.WaitForAssertion(() => Assert.AreEqual(1, cut.Find($"#{nameof(IoTEdgeModel.ImageUrl)}").ChildElementCount));
+ cut.WaitForAssertion(() => Assert.IsFalse(string.IsNullOrEmpty(cut.Find($"#{nameof(IoTEdgeModel.ImageUrl)}").Attributes["src"]?.Value)));
var avatar = cut.WaitForElement($"#{nameof(IoTEdgeModel.ImageUrl)}");
Assert.IsNotNull(avatar);
@@ -368,7 +368,7 @@ public void DeleteAvatarShouldRemoveTheImage()
deleteAvatarBtn.Click();
// Assert
- cut.WaitForAssertion(() => Assert.AreEqual(0, cut.Find($"#{nameof(IoTEdgeModel.ImageUrl)}").ChildElementCount));
+ cut.WaitForAssertion(() => Assert.IsTrue(string.IsNullOrEmpty(cut.Find($"#{nameof(IoTEdgeModel.ImageUrl)}").Attributes["src"]?.Value)));
cut.WaitForAssertion(() => MockRepository.VerifyAll());
}