Skip to content

Commit

Permalink
Display form error messages on CreateDevice & DeviceDetail pages (#160)
Browse files Browse the repository at this point in the history
* Validation on CreateDevicePage

* Validation on DeviceDetailPage
  • Loading branch information
audserraCGI authored Feb 1, 2022
1 parent bb5c28a commit 8538f8f
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 99 deletions.
149 changes: 91 additions & 58 deletions src/AzureIoTHub.Portal/Client/Pages/Devices/CreateDevicePage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -27,64 +27,88 @@
</MudItem>
<MudItem xs="12" sm="8" md="9">
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText>Device Details</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudGrid>
<MudItem xs="12">
<MudTextField @bind-Value="@Device.DeviceID" Label="Device ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12" md="6">
<MudSelect T="string" @bind-Value="@Device.DeviceType"
Dense="true" Variant="Variant.Outlined"
For="@(()=> Device.DeviceType)">
<MudSelectItem Value="@("LoRa Device")" />
<MudSelectItem Value="@("Other")" />
</MudSelect>
</MudItem>
<MudItem xs="12" md="6">
<MudAutocomplete T="DeviceModel"
Dense="true" Variant="Variant.Outlined"
SearchFunc="@Search"
ValueChanged="@ModelSelected"
ToStringFunc="@(x => x.Name)"
ResetValueOnEmptyText="true"
Immediate="true" Clearable="true"
CoerceText="true" CoerceValue="false" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AssetId" Label="IoT Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.LocationCode" Label="Location Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12">
<MudText>
<b>Status</b>
</MudText>
<MudText Typo="Typo.body2">
Means that the device could connect to the platform.
</MudText>
<MudSwitch @bind-Checked="@Device.IsEnabled" Color="Color.Secondary" />
</MudItem>

<MudSpacer />

<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppEUI" Label="OTAA AppEUI" Variant="Variant.Outlined" ReadOnly="true" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppKey" Label="OTAA AppKey" Variant="Variant.Outlined" />
</MudItem>

</MudGrid>
</MudCardContent>
<MudCardActions Class="pb-4 pl-4">
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" @onclick="SaveDevice">Save Changes</MudButton>
</MudCardActions>
<EditForm Model="@Device" OnValidSubmit="SaveDevice" OnInvalidSubmit="HandleInvalidSubmit">
<DataAnnotationsValidator />
<MudCardHeader>
<CardHeaderContent>
<MudText>Device Details</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudGrid>
<MudItem xs="12">
<MudTextField @bind-Value="@Device.DeviceID"
Label="Device ID"
Variant="Variant.Outlined"
For="@(()=> Device.DeviceID)"
Required="true"
HelperText="DeviceID must contain 16 hexadecimal characters (numbers from 0 to 9 and/or letters from A to F)"
/>
</MudItem>
<MudItem xs="12" md="6">
<MudSelect T="string" @bind-Value="@Device.DeviceType"
Dense="true" Variant="Variant.Outlined"
For="@(()=> Device.DeviceType)">
<MudSelectItem Value="@("LoRa Device")" />
<MudSelectItem Value="@("Other")" />
</MudSelect>
</MudItem>
<MudItem xs="12" md="6">
<MudAutocomplete T="DeviceModel"
Label="Model Name*"
Dense="true" Variant="Variant.Outlined"
SearchFunc="@Search"
ValueChanged="@ModelSelected"
ToStringFunc="@(x => x.Name)"
ResetValueOnEmptyText="true"
Immediate="true" Clearable="true"
CoerceText="true" CoerceValue="false" />
@if (Device.ModelName == null && displayValidationErrorMessages)
{
<p class="validation-error-message">The Model Name field is required.</p>
}
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AssetId" Label="IoT Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.LocationCode" Label="Location Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12">
<MudText>
<b>Status</b>
</MudText>
<MudSwitch @bind-Checked="@Device.IsEnabled" Color="Color.Secondary" />
@if (Device.IsEnabled)
{
<MudText Typo="Typo.body2">The device <b>can</b> connect to the platform.</MudText>
}
else
{
<MudText Typo="Typo.body2">The device <b>cannot</b> connect to the platform.</MudText>
}
</MudItem>

<MudSpacer />

<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppEUI"
Label="OTAA AppEUI"
Variant="Variant.Outlined"
For="@(()=> Device.AppEUI)"
ReadOnly="true"
Required="true"
HelperText="OTAA AppEUI is automatically set from the selected model" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppKey" Label="OTAA AppKey" Variant="Variant.Outlined" />
</MudItem>
</MudGrid>
</MudCardContent>
<MudCardActions Class="pb-4 pl-4">
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">Save Changes</MudButton>
</MudCardActions>
</EditForm>
</MudCard>
</MudItem>
</MudGrid>
Expand All @@ -98,6 +122,8 @@

private IEnumerable<DeviceModel> DeviceModelList { get; set; } = new List<DeviceModel>();

private bool displayValidationErrorMessages = false;

protected override async Task OnInitializedAsync()
{
Device.DeviceType = "LoRa Device";
Expand Down Expand Up @@ -134,6 +160,13 @@
}
}

private void HandleInvalidSubmit(EditContext context)
{
// Invalid submit manually handled
// Waiting for MudBlazor MudAutocomplete issue #2674 to be fixed
displayValidationErrorMessages = true;
}

/// <summary>
/// Allows to autocomplete the Device Model field in the form.
/// </summary>
Expand Down
90 changes: 51 additions & 39 deletions src/AzureIoTHub.Portal/Client/Pages/Devices/DeviceDetailPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -44,50 +44,62 @@
<MudAvatar Image="@Device.ImageUrl" Style="height:100px; width: auto; border-radius: 0; background: transparent " />
</div>
<MudText Align="Align.Center" Typo="Typo.h6">@Device.ModelName</MudText>

@if (string.IsNullOrEmpty(Device.ModelId))
{
<MudText Align="Align.Center" Typo="Typo.body1" Color="Color.Error">No model selected</MudText>
<MudText Align="Align.Center" Typo="Typo.body2" Color="Color.Error">The device cannot be updated</MudText>
}
</MudCardContent>
</MudCard>
</MudItem>
<MudItem xs="12" sm="8" md="9">
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText>Device Details</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudGrid>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AssetId" Label="IoT Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.LocationCode" Label="Location Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12">
<MudText>
<b>Status</b>
</MudText>
<MudText Typo="Typo.body2">
Means that the device could connect to the platform.
</MudText>
<MudSwitch @bind-Checked="@Device.IsEnabled" Color="Color.Secondary" />
</MudItem>

<MudSpacer />

<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppEUI" Label="OTAA AppEUI" Variant="Variant.Outlined" ReadOnly="true" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppKey" Label="OTAA AppKey" Variant="Variant.Outlined" />
</MudItem>

</MudGrid>
</MudCardContent>
<MudCardActions Class="pb-4 pl-4">
<MudButton Variant="Variant.Filled" Color="Color.Error" Class="ml-auto" @onclick="DeleteDevice">Delete Device</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-4" @onclick="SaveDevice">Save Changes</MudButton>
</MudCardActions>
<EditForm Model="@Device" OnValidSubmit="SaveDevice">
<DataAnnotationsValidator />
<MudCardHeader>
<CardHeaderContent>
<MudText>Device Details</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudGrid>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AssetId" Label="IoT Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.LocationCode" Label="Location Asset ID" Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12">
<MudText>
<b>Status</b>
</MudText>
<MudSwitch @bind-Checked="@Device.IsEnabled" Color="Color.Secondary" />
@if (Device.IsEnabled)
{
<MudText Typo="Typo.body2">The device <b>can</b> connect to the platform.</MudText>
}
else
{
<MudText Typo="Typo.body2">The device <b>cannot</b> connect to the platform.</MudText>
}
</MudItem>

<MudSpacer />

<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppEUI" Label="OTAA AppEUI" Variant="Variant.Outlined" ReadOnly="true" Required="true" HelperText="OTAA AppEUI is automatically set from the selected model" />
</MudItem>
<MudItem xs="12" md="6">
<MudTextField @bind-Value="@Device.AppKey" Label="OTAA AppKey" Variant="Variant.Outlined" />
</MudItem>

</MudGrid>
</MudCardContent>
<MudCardActions Class="pb-4 pl-4">
<MudButton Variant="Variant.Filled" Color="Color.Error" Class="ml-auto" @onclick="DeleteDevice">Delete Device</MudButton>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-4">Save Changes</MudButton>
</MudCardActions>
</EditForm>
</MudCard>
</MudItem>
<MudItem xs="12">
Expand Down
2 changes: 1 addition & 1 deletion src/AzureIoTHub.Portal/Client/wwwroot/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
margin-right : 10px;
}*/

.custom-validation-error-txt {
.validation-error-message {
color: var(--mud-palette-error) !important;
margin: 0;
font-size: .75rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace AzureIoTHub.Portal.Shared.Models.Device
public class DeviceDetails
{
[Required]
[RegularExpression("^[a-zA-Z0-9]*$", ErrorMessage = "Only Alphabets and Numbers allowed.")]
[RegularExpression("^[A-F0-9]{16}$", ErrorMessage = "DeviceID must contain 16 hexadecimal characters (numbers from 0 to 9 and/or letters from A to F)")]
public string DeviceID { get; set; }

public string ImageUrl { get; set; }
Expand Down

0 comments on commit 8538f8f

Please sign in to comment.