diff --git a/RobotApp.Client/ClientRenderMode.cs b/RobotApp.Client/ClientRenderMode.cs new file mode 100644 index 0000000..def79c3 --- /dev/null +++ b/RobotApp.Client/ClientRenderMode.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Components.Web; + +namespace RobotApp.Client; + +public class ClientRenderMode +{ + public static InteractiveWebAssemblyRenderMode InteractiveWebAssemblyNoPrerender { get; } = new(prerender: false); +} diff --git a/RobotApp.Client/Layout/MainLayout.razor b/RobotApp.Client/Layout/MainLayout.razor deleted file mode 100644 index 81e3cf1..0000000 --- a/RobotApp.Client/Layout/MainLayout.razor +++ /dev/null @@ -1,20 +0,0 @@ -@inherits LayoutComponentBase -@using MudBlazor - -
- - - - - - -
- @Body -
-
- - - - - - diff --git a/RobotApp.Client/Layout/MainLayout.razor.css b/RobotApp.Client/Layout/MainLayout.razor.css deleted file mode 100644 index da43ded..0000000 --- a/RobotApp.Client/Layout/MainLayout.razor.css +++ /dev/null @@ -1,17 +0,0 @@ - -.app-shell { - display: flex; - min-height: 100vh; - min-width: 100vw; - width: 100vw; - height: 100vh; - overflow: hidden; - flex-direction: row; -} - -.page { - flex: 1 1 auto; - min-width: 0; - display: flex; - overflow: hidden; -} diff --git a/RobotApp.Client/Layout/NavMenu.razor b/RobotApp.Client/Layout/NavMenu.razor deleted file mode 100644 index da332e9..0000000 --- a/RobotApp.Client/Layout/NavMenu.razor +++ /dev/null @@ -1,78 +0,0 @@ -@using Microsoft.AspNetCore.Components.Routing - - - - - -@code { - public class NavModel - { - public string Icon { get; set; } = ""; - public string Path { get; set; } = ""; - public string Label { get; set; } = ""; - public NavLinkMatch Match { get; set; } - } - - public NavModel[] Navs = [ - new(){Icon = "mdi-view-dashboard", Path="/", Label = "Dashboard", Match = NavLinkMatch.All}, - new(){Icon = "mdi-map-legend", Path="/Maps-manager", Label = "Mapping", Match = NavLinkMatch.All}, - ]; - - private bool collapseNavMenu = true; - - private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; - - private void ToggleNavMenu() - { - collapseNavMenu = !collapseNavMenu; - } -} diff --git a/RobotApp.Client/MainLayout.razor b/RobotApp.Client/MainLayout.razor new file mode 100644 index 0000000..373fcfd --- /dev/null +++ b/RobotApp.Client/MainLayout.razor @@ -0,0 +1,85 @@ +@inherits LayoutComponentBase + + + +
+ + +
+ @Body +
+
+ +@code{ + public class NavModel + { + public string Icon { get; set; } = ""; + public string Path { get; set; } = ""; + public string Label { get; set; } = ""; + public NavLinkMatch Match { get; set; } + } + + public NavModel[] Navs = [ + new(){Icon = "mdi-view-dashboard", Path="/", Label = "Dashboard", Match = NavLinkMatch.All}, + new(){Icon = "mdi-map-legend", Path="/maps-manager", Label = "Mapping", Match = NavLinkMatch.All}, + ]; + + private bool collapseNavMenu = true; + + private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; + + private void ToggleNavMenu() + { + collapseNavMenu = !collapseNavMenu; + } +} + diff --git a/RobotApp.Client/Layout/NavMenu.razor.css b/RobotApp.Client/MainLayout.razor.css similarity index 90% rename from RobotApp.Client/Layout/NavMenu.razor.css rename to RobotApp.Client/MainLayout.razor.css index f4221f4..b57ef21 100644 --- a/RobotApp.Client/Layout/NavMenu.razor.css +++ b/RobotApp.Client/MainLayout.razor.css @@ -1,3 +1,21 @@ +.app-shell { + display: flex; + min-height: 100vh; + min-width: 100vw; + width: 100vw; + height: 100vh; + overflow: hidden; + flex-direction: row; +} + +.page { + flex: 1 1 auto; + min-width: 0; + display: flex; + overflow: hidden; +} + + .sidebar { background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); diff --git a/RobotApp.Client/Pages/AssemblyLayout.razor b/RobotApp.Client/Pages/AssemblyLayout.razor new file mode 100644 index 0000000..faec1f3 --- /dev/null +++ b/RobotApp.Client/Pages/AssemblyLayout.razor @@ -0,0 +1,12 @@ +@inherits LayoutComponentBase +@layout RobotApp.Client.MainLayout + + + + + + +@Body \ No newline at end of file diff --git a/RobotApp.Client/Pages/Auth.razor b/RobotApp.Client/Pages/Auth.razor deleted file mode 100644 index b7bbe6e..0000000 --- a/RobotApp.Client/Pages/Auth.razor +++ /dev/null @@ -1,13 +0,0 @@ -@page "/auth" - -@using Microsoft.AspNetCore.Authorization - -@attribute [Authorize] - -Auth - -

You are authenticated

- - - Hello @context.User.Identity?.Name! - diff --git a/RobotApp.Client/Pages/Components/Mapping/MapPreview.razor b/RobotApp.Client/Pages/Components/Mapping/MapPreview.razor new file mode 100644 index 0000000..e66b320 --- /dev/null +++ b/RobotApp.Client/Pages/Components/Mapping/MapPreview.razor @@ -0,0 +1,40 @@ +@inject HttpClient Http + +
+ @MapName +
+
+ map image +
+ + DOWNLOAD + +
+
+ +@code { + private bool Disable = true; + private string imageSrc = "/images/Image-not-found.png"; + private string MapName = "Map preview"; + private Guid MapId = Guid.Empty; + + + public void SetMapPreview(MapDto? map) + { + if (map is null) + { + Disable = true; + MapName = "Map preview"; + imageSrc = "/images/Image-not-found.png"; + MapId = Guid.Empty; + } + else + { + imageSrc = $"api/Images/map/{map.Id}?t={DateTime.Now}"; + MapName = map.Name; + MapId = map.Id; + Disable = false; + } + StateHasChanged(); + } +} diff --git a/RobotApp.Client/Pages/Components/Mapping/MapPreview.razor.css b/RobotApp.Client/Pages/Components/Mapping/MapPreview.razor.css new file mode 100644 index 0000000..ac1ded4 --- /dev/null +++ b/RobotApp.Client/Pages/Components/Mapping/MapPreview.razor.css @@ -0,0 +1,42 @@ +.map-item { + display: flex; + justify-content: center; + width: 100%; + height: fit-content; +} + + .map-item img { + justify-content: center; + width: 95%; + height: 400px; + object-fit: contain; + border-radius: 10px; + image-rendering: pixelated; + } + +.title { + display: flex; + height: 77px; + width: 100%; + justify-content: center; + align-content: center; + /*border-bottom: 0.5px solid gray;*/ + font-size: 30px; + flex-wrap: wrap; + padding-bottom: .5rem; +} + +.map-update-item { + display: flex; + justify-content: center; + width: 100%; + height: fit-content; +} + + .map-update-item img { + width: 100%; + height: 400px; + object-fit: contain; + border-radius: 10px; + image-rendering: pixelated; + } diff --git a/RobotApp.Client/Pages/Components/Mapping/MapTable.razor b/RobotApp.Client/Pages/Components/Mapping/MapTable.razor new file mode 100644 index 0000000..1a306cd --- /dev/null +++ b/RobotApp.Client/Pages/Components/Mapping/MapTable.razor @@ -0,0 +1,165 @@ +@inject HttpClient Http + + + +
+ + + Maps + + + 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 + + + Active + Delete + + + +
+ +
+
+
+
+ +@code { + + private string txtSearch = ""; + private bool IsLoading = false; + + private List Maps = []; + private List MapsShow = []; + + private int selectedRowNumber = -1; + private MapDto MapSelected = new(); + + private MudTable? Table; + + private MapPreview? MapPreviewRef; + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (!firstRender) return; + + // 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(MapDto 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(map => + { + if (FilterFunc(map)) tasks.Add(map); + }); + 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(MapDto 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; + // MapPreviewRef?.SetMapPreview(MapSelected); + return "selected"; + } + else + { + return string.Empty; + } + } +} diff --git a/RobotApp.Client/Pages/Components/Mapping/MapTable.razor.css b/RobotApp.Client/Pages/Components/Mapping/MapTable.razor.css new file mode 100644 index 0000000..6deaf98 --- /dev/null +++ b/RobotApp.Client/Pages/Components/Mapping/MapTable.razor.css @@ -0,0 +1,5 @@ +.map-preview { + width: 20%; + height: 100%; + border-left: 1px solid silver; +} diff --git a/RobotApp.Client/Components/Mapping/MapView.razor b/RobotApp.Client/Pages/Components/Mapping/MapView.razor similarity index 100% rename from RobotApp.Client/Components/Mapping/MapView.razor rename to RobotApp.Client/Pages/Components/Mapping/MapView.razor diff --git a/RobotApp.Client/Pages/Counter.razor b/RobotApp.Client/Pages/Counter.razor deleted file mode 100644 index ef23cb3..0000000 --- a/RobotApp.Client/Pages/Counter.razor +++ /dev/null @@ -1,18 +0,0 @@ -@page "/counter" - -Counter - -

Counter

- -

Current count: @currentCount

- - - -@code { - private int currentCount = 0; - - private void IncrementCount() - { - currentCount++; - } -} diff --git a/RobotApp.Client/Pages/MapsManager.razor b/RobotApp.Client/Pages/MapsManager.razor index ebf6ea2..cff3a98 100644 --- a/RobotApp.Client/Pages/MapsManager.razor +++ b/RobotApp.Client/Pages/MapsManager.razor @@ -1,181 +1,20 @@ @page "/maps-manager" -@using MudBlazor -@using RobotApp.Common.Shares.Dtos + +@rendermode InteractiveWebAssemblyNoPrerender @attribute [Authorize] -@inject HttpClient Http Map Manager - - -
-
-
- - - 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 - -
-
-
- -
- -
-
-
-
+
+
+
-
+
+
@code { - private string txtSearch = ""; - private bool IsLoading = false; - - private List Maps = []; private List MapsShow = []; - - private int selectedRowNumber = -1; - private MapDto MapSelected = new(); - - private MudTable? Table; protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - if (!firstRender) return; - - 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(MapDto 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(map => - { - if (FilterFunc(map)) tasks.Add(map); - }); - 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(MapDto 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; - } - } } diff --git a/RobotApp.Client/Pages/Weather.razor b/RobotApp.Client/Pages/Weather.razor deleted file mode 100644 index dd36b18..0000000 --- a/RobotApp.Client/Pages/Weather.razor +++ /dev/null @@ -1,63 +0,0 @@ -@page "/weather" - -Weather - -

Weather

- -

This component demonstrates showing data.

- -@if (forecasts == null) -{ -

Loading...

-} -else -{ - - - - - - - - - - - @foreach (var forecast in forecasts) - { - - - - - - - } - -
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
-} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - // Simulate asynchronous loading to demonstrate a loading indicator - await Task.Delay(500); - - var startDate = DateOnly.FromDateTime(DateTime.Now); - var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; - forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = startDate.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = summaries[Random.Shared.Next(summaries.Length)] - }).ToArray(); - } - - private class WeatherForecast - { - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string? Summary { get; set; } - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - } -} diff --git a/RobotApp.Client/Pages/_Imports.razor b/RobotApp.Client/Pages/_Imports.razor new file mode 100644 index 0000000..d8c136a --- /dev/null +++ b/RobotApp.Client/Pages/_Imports.razor @@ -0,0 +1,16 @@ +@layout RobotApp.Client.Pages.AssemblyLayout +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using static RobotApp.Client.ClientRenderMode +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using RobotApp.Client +@using Microsoft.AspNetCore.Authorization +@using MudBlazor +@using RobotApp.Common.Shares +@using RobotApp.Common.Shares.Dtos diff --git a/RobotApp.Client/Program.cs b/RobotApp.Client/Program.cs index 56ebe4b..6c76300 100644 --- a/RobotApp.Client/Program.cs +++ b/RobotApp.Client/Program.cs @@ -1,11 +1,20 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using MudBlazor.Services; +using System.Globalization; +CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.Services.AddAuthorizationCore(); builder.Services.AddCascadingAuthenticationState(); builder.Services.AddAuthenticationStateDeserialization(); -builder.Services.AddMudServices(); + +builder.Services.AddScoped(_ => new HttpClient() { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); +builder.Services.AddMudServices(config => +{ + config.SnackbarConfiguration.VisibleStateDuration = 2000; + config.SnackbarConfiguration.HideTransitionDuration = 500; + config.SnackbarConfiguration.ShowTransitionDuration = 500; +}); await builder.Build().RunAsync(); diff --git a/RobotApp.Client/RobotApp.Client.csproj b/RobotApp.Client/RobotApp.Client.csproj index 92168bf..c65ed05 100644 --- a/RobotApp.Client/RobotApp.Client.csproj +++ b/RobotApp.Client/RobotApp.Client.csproj @@ -18,4 +18,9 @@ + + + + + diff --git a/RobotApp.Client/_Imports.razor b/RobotApp.Client/_Imports.razor index 53fa057..449fd7f 100644 --- a/RobotApp.Client/_Imports.razor +++ b/RobotApp.Client/_Imports.razor @@ -5,6 +5,7 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using static Microsoft.AspNetCore.Components.Web.RenderMode +@using static RobotApp.Client.ClientRenderMode @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using RobotApp.Client diff --git a/RobotApp.sln b/RobotApp.sln index edd2672..258b320 100644 --- a/RobotApp.sln +++ b/RobotApp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 18 -VisualStudioVersion = 18.0.11018.127 d18.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36511.14 d17.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobotApp", "RobotApp\RobotApp.csproj", "{BF0BB137-2EF9-4E1B-944E-9BF41C5284F7}" EndProject diff --git a/RobotApp/Components/App.razor b/RobotApp/Components/App.razor index e304093..7c4ad1b 100644 --- a/RobotApp/Components/App.razor +++ b/RobotApp/Components/App.razor @@ -4,23 +4,23 @@ + RobotApp - + - - + - + @@ -28,7 +28,7 @@ Not found - +

Không tìm thấy trang.

@@ -39,7 +39,7 @@ - + diff --git a/RobotApp.Client/Pages/Home.razor b/RobotApp/Components/Pages/Home.razor similarity index 77% rename from RobotApp.Client/Pages/Home.razor rename to RobotApp/Components/Pages/Home.razor index 84411a1..0e760a6 100644 --- a/RobotApp.Client/Pages/Home.razor +++ b/RobotApp/Components/Pages/Home.razor @@ -1,4 +1,7 @@ @page "/" @using Microsoft.AspNetCore.Authorization + +@rendermode InteractiveServer + @attribute [Authorize]

Welcome to RobotApp!

diff --git a/RobotApp/Components/ServerLayout.razor b/RobotApp/Components/ServerLayout.razor new file mode 100644 index 0000000..72445f5 --- /dev/null +++ b/RobotApp/Components/ServerLayout.razor @@ -0,0 +1,12 @@ +@inherits LayoutComponentBase +@layout RobotApp.Client.MainLayout + + + + + + +@Body \ No newline at end of file diff --git a/RobotApp/Program.cs b/RobotApp/Program.cs index 353c5dd..e81d55c 100644 --- a/RobotApp/Program.cs +++ b/RobotApp/Program.cs @@ -6,7 +6,6 @@ using RobotApp.Components; using RobotApp.Components.Account; using RobotApp.Data; using RobotApp.Services.Robot; -using RobotApp.Client; var builder = WebApplication.CreateBuilder(args); diff --git a/RobotApp/RobotApp.csproj b/RobotApp/RobotApp.csproj index 64234bd..a0f9339 100644 --- a/RobotApp/RobotApp.csproj +++ b/RobotApp/RobotApp.csproj @@ -16,7 +16,6 @@ - diff --git a/RobotApp/robot.db b/RobotApp/robot.db index 8359201..27b6947 100644 Binary files a/RobotApp/robot.db and b/RobotApp/robot.db differ