@page "/navigation-maps"
@attribute [Authorize]
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using RobotNet.MapShares
@using RobotNet.MapShares.Dtos
@using System.Net.Http.Headers
@using RobotNet.Shares
@using RobotNet.WebApp.Maps.Components
@inject NavigationManager NavManager
@inject IHttpClientFactory HttpClientFactory
@inject IJSRuntime JSRuntime
@inject ISnackbar Snackbar
@inject IDialogService Dialog
Map Manager
IMPORT
NEW
Nr
Name
Width (m)
Height (m)
Resolution (m/px)
OriginX
OriginY
@(Table?.CurrentPage * Table?.RowsPerPage + MapsShow.IndexOf(context) + 1)
@context.Name
@context.Width
@context.Height
@context.Resolution
@context.OriginX
@context.OriginY
Edit
Delete
Active
Create New Map
Cancel
Create
Update Map
Cancel
Update
Import New Map
Cancel
Create
@code {
private string txtSearch = "";
private bool IsLoading = false;
private List Maps = [];
private List MapsShow = [];
private MudTable? Table;
private int selectedRowNumber = -1;
private MapInfoDto MapSelected = new();
private bool IsCreateMapVisible { get; set; }
private readonly MapCreateModel MapCreateModel = new();
private IBrowserFile? MapCreateImage { get; set; }
private string? ProjectionImageFilePreview { get; set; }
private bool IsUpdateMapVisible { get; set; }
private readonly MapUpdateModel MapUpdateModel = new();
private NavigationMapPreview NavigationMapPreviewRef = default!;
private MapExportDto MapImport = default!;
private bool IsImportMapVisible { get; set; }
private string? ProjectionImportImageFilePreview { get; set; }
private HttpClient Http = default!;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (!firstRender) return;
Http = HttpClientFactory.CreateClient("MapManagerAPI");
await LoadMaps();
}
private async Task LoadMaps()
{
try
{
IsLoading = true;
Maps.Clear();
StateHasChanged();
var maps = await Http.GetFromJsonAsync>($"api/MapsManager?txtSearch={txtSearch}");
Maps.AddRange(maps ?? []);
Table?.ReloadServerData();
IsLoading = false;
StateHasChanged();
}
catch
{
return;
}
}
private void TextSearchChanged(string text)
{
txtSearch = text;
Table?.ReloadServerData();
}
private bool FilterFunc(MapInfoDto map)
{
if (string.IsNullOrWhiteSpace(txtSearch))
return true;
if (map.Name is not null && map.Name.Contains(txtSearch, StringComparison.OrdinalIgnoreCase))
return true;
if ($"{map.Name}".Contains(txtSearch))
return true;
return false;
}
private Task> ReloadData(TableState state, CancellationToken _)
{
MapsShow.Clear();
var tasks = new List();
Maps.ForEach(task =>
{
if (FilterFunc(task)) tasks.Add(task);
});
MapsShow = tasks.Skip(state.Page * state.PageSize).Take(state.PageSize).ToList();
return Task.FromResult(new TableData() { TotalItems = tasks.Count, Items = MapsShow });
}
private void RowClickEvent(TableRowClickEventArgs tableRowClickEventArgs) { }
private string SelectedRowClassFunc(MapInfoDto element, int rowNumber)
{
if (selectedRowNumber == rowNumber && Table?.SelectedItem != null && !Table.SelectedItem.Equals(element))
{
return string.Empty;
}
else if (selectedRowNumber == rowNumber && Table?.SelectedItem != null && Table.SelectedItem.Equals(element))
{
return "selected";
}
else if (Table?.SelectedItem != null && Table.SelectedItem.Equals(element))
{
selectedRowNumber = rowNumber;
MapSelected = element;
NavigationMapPreviewRef.SetMapPreview(MapSelected);
return "selected";
}
else
{
return string.Empty;
}
}
private void OpenCreateMap()
{
MapCreateModel.Name = string.Empty;
MapCreateModel.OriginX = 0;
MapCreateModel.OriginY = 0;
MapCreateModel.Resolution = 0.1;
ProjectionImageFilePreview = "/images/Image-not-found.png";
MapCreateImage = null;
IsCreateMapVisible = true;
StateHasChanged();
}
private async Task MapCreateImageChanged(InputFileChangeEventArgs e)
{
MapCreateImage = e.File;
if (MapCreateImage is not null)
{
var buffers = new byte[MapCreateImage.Size];
var path = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
await using var fs = new FileStream(path, FileMode.Create);
await MapCreateImage.OpenReadStream(MapCreateImage.Size).CopyToAsync(fs);
fs.Position = 0;
await fs.ReadAsync(buffers);
fs.Close();
File.Delete(path);
ProjectionImageFilePreview = $"data:{MapCreateImage.ContentType};base64,{Convert.ToBase64String(buffers)}";
StateHasChanged();
}
}
private async Task CreateNewMap()
{
try
{
if (MapCreateImage is null || string.IsNullOrEmpty(ProjectionImageFilePreview))
{
Snackbar.Add("Ảnh map chưa được chọn.", Severity.Warning);
return;
}
if (string.IsNullOrEmpty(MapCreateModel.Name))
{
Snackbar.Add("Map's name không được để trống.", Severity.Warning);
return;
}
var nameInvalid = MapEditorHelper.NameChecking(MapCreateModel.Name);
if (!nameInvalid.IsSuccess)
{
Snackbar.Add(nameInvalid.returnStr, Severity.Warning);
return;
}
using var content = new MultipartFormDataContent
{
{ new StringContent(MapCreateModel.Name ?? String.Empty), nameof(MapCreateModel.Name) },
{ new StringContent(MapCreateModel.OriginX.ToString()), nameof(MapCreateModel.OriginX) },
{ new StringContent(MapCreateModel.OriginY.ToString()), nameof(MapCreateModel.OriginY) },
{ new StringContent(MapCreateModel.Resolution.ToString()), nameof(MapCreateModel.Resolution) },
};
var fileContent = new StreamContent(MapCreateImage.OpenReadStream(maxAllowedSize: 20480000));
fileContent.Headers.ContentType = new MediaTypeHeaderValue(MapCreateImage.ContentType);
content.Add(fileContent, "Image", MapCreateImage.Name);
var response = await (await Http.PostAsync("api/MapsManager", content)).Content.ReadFromJsonAsync>();
if (response is null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Lỗi chưa xác định.", Severity.Error);
else if (response.Data is null) Snackbar.Add("Hệ thống không thể tạo bản đồ này", Severity.Error);
else
{
Maps.Add(response.Data);
Table?.ReloadServerData();
Snackbar.Add($"Tạo map {MapCreateModel.Name} thành công.", Severity.Success);
}
IsCreateMapVisible = false;
StateHasChanged();
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect();
return;
}
}
private void OpenUpdateMap(MapInfoDto map)
{
MapUpdateModel.Id = map.Id;
MapUpdateModel.Name = map.Name;
MapUpdateModel.OriginX = map.OriginX;
MapUpdateModel.OriginY = map.OriginY;
MapUpdateModel.Resolution = map.Resolution;
IsUpdateMapVisible = true;
StateHasChanged();
}
private async Task UpdateMap()
{
var nameErrors = MapEditorHelper.NameChecking(MapUpdateModel.Name);
if (!nameErrors.IsSuccess)
{
Snackbar.Add(nameErrors.returnStr, Severity.Warning);
return;
}
var result = await (await Http.PutAsJsonAsync($"api/MapsManager/{MapUpdateModel.Id}", MapUpdateModel)).Content.ReadFromJsonAsync>();
if (result == null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
else if (!result.IsSuccess) Snackbar.Add(result.Message, Severity.Error);
else if (result.Data is null)
{
Snackbar.Add("Dữ liệu không hợp lệ", Severity.Error);
}
else
{
var map = Maps.FirstOrDefault(map => map.Id == MapUpdateModel.Id);
if (map is not null)
{
map.Name = result.Data.Name;
map.OriginX = result.Data.OriginX;
map.OriginY = result.Data.OriginY;
map.Resolution = result.Data.Resolution;
map.Width = result.Data.Width;
map.Height = result.Data.Height;
map.Active = result.Data.Active;
Snackbar.Add("Cập nhật thành công", Severity.Success);
}
else Snackbar.Add("Map không tồn tại", Severity.Error);
}
IsUpdateMapVisible = false;
StateHasChanged();
}
private async Task DeleteMap(Guid mapId)
{
var parameters = new DialogParameters
{
{ x => x.Content, "Bạn có chắc chắn muốn xóa map đi không?" },
{ x => x.ConfirmText, "Delete" },
{ x => x.Color, Color.Secondary }
};
var ConfirmDelete = await Dialog.ShowAsync("Xoá Map", parameters);
var result = await ConfirmDelete.Result;
if (result is not null && result.Data is not null && bool.TryParse(result.Data.ToString(), out bool data) && data)
{
var response = await Http.DeleteFromJsonAsync($"api/MapsManager/{mapId}");
if (response is null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Lỗi chưa xác định.", Severity.Error);
else
{
var map = Maps.FirstOrDefault(m => m.Id == mapId);
if (map is not null)
{
if (map.Id == MapSelected.Id)
{
NavigationMapPreviewRef.SetMapPreview(null);
Table?.SetSelectedItem(null);
selectedRowNumber = -1;
}
Maps.Remove(map);
Table?.ReloadServerData();
Snackbar.Add($"Xóa map thành công.", Severity.Success);
}
else Snackbar.Add($"Map không tồn tại.", Severity.Warning);
}
StateHasChanged();
}
}
private async Task MapActiveToggle(Guid mapId, bool value)
{
var result = await (await Http.PutAsJsonAsync($"api/MapsManager/active", new MapActiveModel() { Id = mapId, Active = value })).Content.ReadFromJsonAsync();
if (result is null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
else if (!result.IsSuccess) Snackbar.Add(result.Message ?? "Lỗi chưa xác định.", Severity.Error);
else
{
var map = Maps.FirstOrDefault(map => map.Id == mapId);
if (map is not null)
{
map.Active = value;
Snackbar.Add("Cập nhật thành công", Severity.Success);
}
else Snackbar.Add($"Map không tồn tại.", Severity.Warning);
}
StateHasChanged();
}
private async Task MapImageChangedCallBack(Guid mapId)
{
try
{
var mapupdate = await Http.GetFromJsonAsync>($"api/MapsManager/{mapId}");
if (mapupdate is not null && mapupdate.Data is not null)
{
var map = Maps.FirstOrDefault(m => m.Id == mapupdate.Data.Id);
if (map is not null)
{
map.Name = mapupdate.Data.Name;
map.Width = mapupdate.Data.Width;
map.Height = mapupdate.Data.Height;
}
}
StateHasChanged();
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect();
return;
}
}
private async Task OnMapImportChanged(InputFileChangeEventArgs e)
{
if (e.File is not null)
{
using var content = new MultipartFormDataContent();
var fileContent = new StreamContent(e.File.OpenReadStream(maxAllowedSize: 10240000));
if (!string.IsNullOrEmpty(e.File.ContentType)) fileContent.Headers.ContentType = new MediaTypeHeaderValue(e.File.ContentType);
content.Add(fileContent, "importmap", e.File.Name);
var response = await (await Http.PostAsync("api/MapExport/decrypt", content)).Content.ReadFromJsonAsync>();
if (response is null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
else if (!response.IsSuccess) Snackbar.Add($"Có lỗi xảy ra: {response.Message}", Severity.Error);
else
{
if (response.Data is not null)
{
MapImport = response.Data;
ProjectionImportImageFilePreview = $"data:image/png;base64,{Convert.ToBase64String(response.Data.Data.ImageData)}";
IsImportMapVisible = true;
}
else Snackbar.Add("Dữ liệu không hợp lệ", Severity.Warning);
}
StateHasChanged();
}
}
private async Task ImportNewMap()
{
if (string.IsNullOrEmpty(MapImport.Name))
{
Snackbar.Add("Map's name không được để trống.", Severity.Warning);
return;
}
var nameInvalid = MapEditorHelper.NameChecking(MapImport.Name);
if (!nameInvalid.IsSuccess)
{
Snackbar.Add(nameInvalid.returnStr, Severity.Warning);
return;
}
var response = await (await Http.PostAsJsonAsync("api/MapsManager/import", MapImport)).Content.ReadFromJsonAsync>();
if (response is null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Warning);
else if (!response.IsSuccess) Snackbar.Add($"Có lỗi xảy ra: {response.Message}", Severity.Warning);
else
{
if (response.Data is not null)
{
Maps.Add(response.Data);
Table?.ReloadServerData();
Snackbar.Add($"Import bản đồ thành công!", Severity.Success);
}
else Snackbar.Add("Dữ liệu không hợp lệ", Severity.Warning);
}
MapImport = default!;
IsImportMapVisible = false;
StateHasChanged();
}
}