Skip to content

Commit

Permalink
Add label feature #777 (#1621)
Browse files Browse the repository at this point in the history
* Add label feature #777

* Enable filtering devices by labels

* Enable filtering edge devices by labels

* Fix unit tests on DeviceListPage

* Add missing override on lorawan controller

* Add unit tests on LabelsEditor

* Add unit tests on LabelRepository

* Add unit test on GetAvailableLabels

* Update unit test on GetDevices with custom filter

* Remove labels init when null

* Add unit tests on GetAvailableLabels methods on client services

* Add unit tests on GetAvailableLabels on device controllers

* Add unit test on GetAvailableLabels on edge device service

* Update unit test on update edge device to cover delete labels

* Update unit test on get edge devices to cover filter by labels

* Update unit tests on edge model service

* Add unit test on GetAvailableLabels on edge device controller

* Add unit test on search device models on device list page

* Add unit test on search device models on edge device list page

* Render labels on unit test on edge device list page

* Add unit test on search edge model on create edge device page
  • Loading branch information
hocinehacherouf authored Dec 5, 2022
1 parent 0692b89 commit cf525a8
Show file tree
Hide file tree
Showing 72 changed files with 2,254 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
@using AzureIoTHub.Portal.Shared.Models.v10

<MudGrid>

@if (ReadOnlyLabels != null && ReadOnlyLabels.Any())
{
<MudItem xs="12">
<MudText Typo="Typo.h6">Mandatory labels</MudText>
</MudItem>
<MudItem xs="12">
<MudChipSet ReadOnly="true">
@foreach (var label in ReadOnlyLabels)
{
<MudChip Text="@label.Name" Color="Color.Primary" Style="@($"background-color: {label.Color};")" />
}
</MudChipSet>
</MudItem>
}

<MudItem xs="12">
<MudItem xs="12">
<MudText Typo="Typo.h6">Edit labels</MudText>
</MudItem>
<MudGrid>
<MudItem xs="6">
<MudTextField T="string" @bind-Value="labelNameValue" Label="Name" Required="true" Variant="Variant.Text" />
</MudItem>
<MudItem xs="5">
<MudColorPicker @bind-Text="labelColorValue" Label="Label color" DisableToolbar="false" PickerVariant="PickerVariant.Inline" Required="true" />
</MudItem>
<MudItem xs="1">
<MudIconButton id="add-label" Icon="@Icons.Material.Filled.Add" aria-label="add-label" OnClick="@AddLabel" />
</MudItem>
</MudGrid>
</MudItem>
<MudItem xs="12">
<MudChipSet AllClosable="true" OnClose="RemoveLabel">
@foreach (var label in Labels)
{
<MudChip Text="@label.Name" Color="Color.Primary" Style="@($"background-color: {label.Color};")" />
}
</MudChipSet>
</MudItem>

</MudGrid>

@code {

[Parameter]
public List<LabelDto> ReadOnlyLabels { get; set; } = new();

[Parameter]
public List<LabelDto> Labels { get; set; } = new();

private string labelNameValue;
private string labelColorValue;

public void AddLabel()
{
if (string.IsNullOrWhiteSpace(labelNameValue) ||
string.IsNullOrEmpty(labelColorValue) ||
Labels.Any(dto => dto.Name.Equals(labelNameValue)) ||
(ReadOnlyLabels?.Any(label => label.Name.Equals(labelNameValue)) ?? false)) return;

var labelToAdd = new LabelDto
{
Name = labelNameValue,
Color = labelColorValue
};

Labels.Add(labelToAdd);

labelNameValue = string.Empty;
}

public void RemoveLabel(MudChip chip)
{
var labelToDelete = Labels.FirstOrDefault(dto => dto.Name.Equals(chip.Text));

if (labelToDelete == null) return;

Labels.Remove(labelToDelete);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,18 @@
</MudItem>
</MudGrid>
}

<MudGrid>
<MudItem xs="12">
<MudExpansionPanel Text="Labels">
<TitleContent><MudText Typo="Typo.h6">Labels</MudText></TitleContent>
<ChildContent>
<LabelsEditor Labels="Model.Labels" />
</ChildContent>
</MudExpansionPanel>
</MudItem>
</MudGrid>

</MudExpansionPanels>
</MudTabPanel>
@if (IsLoRa)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@
</MudItem>
</MudGrid>
}

<MudGrid>
<MudItem xs="12">
<MudExpansionPanel Text="Labels">
<TitleContent><MudText Typo="Typo.h6">Labels</MudText></TitleContent>
<ChildContent>
<LabelsEditor Labels="Model.Labels" />
</ChildContent>
</MudExpansionPanel>
</MudItem>
</MudGrid>

</MudExpansionPanels>
</MudTabPanel>
@if (IsLoRa)
Expand Down
13 changes: 13 additions & 0 deletions src/AzureIoTHub.Portal.Client/Pages/Devices/CreateDevicePage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@using AzureIoTHub.Portal.Models.v10
@using AzureIoTHub.Portal.Models.v10.LoRaWAN
@using AzureIoTHub.Portal.Shared.Models
@using AzureIoTHub.Portal.Shared.Models.v10;
@using Microsoft.AspNetCore.Components

@attribute [Authorize]
Expand Down Expand Up @@ -164,6 +165,18 @@
</MudExpansionPanel>
</MudItem>
</MudGrid>

<MudGrid>
<MudItem xs="12">
<MudExpansionPanel Text="Labels">
<TitleContent><MudText Typo="Typo.h6">Labels</MudText></TitleContent>
<ChildContent>
<LabelsEditor ReadOnlyLabels="DeviceModel?.Labels" Labels="Device.Labels" />
</ChildContent>
</MudExpansionPanel>
</MudItem>
</MudGrid>

@if (!IsLoRa && Properties.Any())
{
<MudGrid>
Expand Down
12 changes: 12 additions & 0 deletions src/AzureIoTHub.Portal.Client/Pages/Devices/DeviceDetailPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@
</MudExpansionPanel>
</MudItem>
</MudGrid>

<MudGrid>
<MudItem xs="12">
<MudExpansionPanel Text="Labels">
<TitleContent><MudText Typo="Typo.h6">Labels</MudText></TitleContent>
<ChildContent>
<LabelsEditor ReadOnlyLabels="DeviceModel.Labels" Labels="Device.Labels" />
</ChildContent>
</MudExpansionPanel>
</MudItem>
</MudGrid>

@if (!IsLoRa && Properties.Any())
{
<MudGrid>
Expand Down
30 changes: 30 additions & 0 deletions src/AzureIoTHub.Portal.Client/Pages/Devices/DeviceListPage.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@page "/devices"
@using AzureIoTHub.Portal
@using AzureIoTHub.Portal.Models.v10
@using AzureIoTHub.Portal.Shared.Models.v10;
@using System.Web
@using System.IO
@using System.Text.RegularExpressions
Expand Down Expand Up @@ -33,6 +34,20 @@
</MudItem>
}
}

<MudItem xs="12" md="6">
<MudSelect T="LabelDto" Label="Labels" MultiSelection="true" @bind-SelectedValues="selectedLabels"
MultiSelectionTextFunc="@(new Func<List<string>, string>(GetMultiSelectionText))"
Variant="Variant.Outlined">
@foreach (var label in labels)
{
<MudSelectItem T="LabelDto" Value="@label">
<MudChip Text="@label.Name" Color="Color.Primary" Style="@($"background-color: {label.Color};")" />
</MudSelectItem>
}
</MudSelect>
</MudItem>

<MudItem xs="12" md="6">
<MudAutocomplete T="DeviceModelDto"
id="@nameof(DeviceModelDto.ModelId)"
Expand Down Expand Up @@ -264,6 +279,9 @@

private IEnumerable<DeviceTagDto> TagList { get; set; } = new List<DeviceTagDto>();

private IEnumerable<LabelDto> labels = new List<LabelDto>();
private IEnumerable<LabelDto> selectedLabels = new List<LabelDto>();

private int[] pageSizeOptions = new int[] { 2, 5, 10 };

protected override async Task OnInitializedAsync()
Expand All @@ -278,6 +296,7 @@
if (tag.Searchable)
searchTags.Add(tag.Name, "");
}
labels = await DeviceClientService.GetAvailableLabels();
}
catch (ProblemDetailsException exception)
{
Expand Down Expand Up @@ -308,6 +327,11 @@
uri += $"&tag.{searchTag.Key}={searchTag.Value}";
}

foreach(var label in selectedLabels)
{
uri += $"&labels={label.Name}";
}

var result = await DeviceClientService.GetDevices(uri);

return new TableData<DeviceListItem>
Expand Down Expand Up @@ -343,6 +367,7 @@
searchStatus = "";
searchState = "";
searchTags = searchTags.ToDictionary(tag => tag.Key, tag => "");
selectedLabels = new List<LabelDto>();

Search();
}
Expand Down Expand Up @@ -483,4 +508,9 @@
{
menuIsOpen = !menuIsOpen;
}

private string GetMultiSelectionText(List<string> selectedValues)
{
return $"{selectedValues.Count} label{(selectedValues.Count > 1 ? "s have" : " has")} been selected";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
}
else
{
<MudAutocomplete T="IoTEdgeModelListItem"
id="@nameof(IoTEdgeModelListItem.ModelId)"
<MudAutocomplete T="IoTEdgeModel"
id="@nameof(IoTEdgeModel.ModelId)"
@bind-Value="edgeModel"
SearchFunc="@Search"
Label="Model*"
Expand Down Expand Up @@ -143,6 +143,17 @@
</MudExpansionPanel>
</MudItem>
</MudGrid>

<MudGrid>
<MudItem xs="12">
<MudExpansionPanel Text="Labels">
<TitleContent><MudText Typo="Typo.h6">Labels</MudText></TitleContent>
<ChildContent>
<LabelsEditor ReadOnlyLabels="edgeModel?.Labels" Labels="EdgeDevice.Labels" />
</ChildContent>
</MudExpansionPanel>
</MudItem>
</MudGrid>

</MudExpansionPanels>
</MudTabPanel>
Expand All @@ -161,8 +172,8 @@
private IoTEdgeDevice EdgeDevice = new IoTEdgeDevice();

private IEnumerable<IoTEdgeModelListItem> edgeModelList = new List<IoTEdgeModelListItem>();
private IoTEdgeModelListItem _edgeModel;
private IoTEdgeModelListItem edgeModel
private IoTEdgeModel _edgeModel;
private IoTEdgeModel edgeModel
{
get => _edgeModel;
set
Expand Down Expand Up @@ -286,24 +297,34 @@
/// </summary>
/// <param name="value">Text entered in the field</param>
/// <returns>Item of the device model list that matches the user's value</returns>
private async Task<IEnumerable<IoTEdgeModelListItem>> Search(string value)
private async Task<IEnumerable<IoTEdgeModel>> Search(string value)
{
// In real life use an asynchronous function for fetching data from an api.
await Task.Delay(0);

// if text is null or empty, show complete list
if (string.IsNullOrEmpty(value))
return edgeModelList;
return edgeModelList
.Select(m => new IoTEdgeModel
{
ModelId = m.ModelId,
Name = m.Name
});;

return edgeModelList
.Where(x => x.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase));
.Where(x => x.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase))
.Select(m => new IoTEdgeModel
{
ModelId = m.ModelId,
Name = m.Name
});
}

internal async Task ChangeModel(IoTEdgeModelListItem edgeModel)
internal async Task ChangeModel(IoTEdgeModel edgeModel)
{
try
{
this._edgeModel = edgeModel;
this._edgeModel = await this.EdgeModelClientService.GetIoTEdgeModel(edgeModel.ModelId);

this.EdgeDevice = new IoTEdgeDevice()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@
</MudExpansionPanel>
</MudItem>
</MudGrid>

<MudGrid>
<MudItem xs="12">
<MudExpansionPanel Text="Labels">
<TitleContent><MudText Typo="Typo.h6">Labels</MudText></TitleContent>
<ChildContent>
<LabelsEditor ReadOnlyLabels="edgeModel.Labels" Labels="edgeDevice.Labels" />
</ChildContent>
</MudExpansionPanel>
</MudItem>
</MudGrid>
</MudExpansionPanels>
</MudTabPanel>
</MudTabs>
Expand Down
Loading

0 comments on commit cf525a8

Please sign in to comment.