Maxence GUITARD 1 year ago
commit 4ad1d0aaaa

@ -1,12 +1,14 @@
<Router AppAssembly="@typeof(App).Assembly"> <CascadingBlazoredModal>
<Found Context="routeData"> <Router AppAssembly="@typeof(App).Assembly">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <Found Context="routeData">
<FocusOnNavigate RouteData="@routeData" Selector="h1" /> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found> <FocusOnNavigate RouteData="@routeData" Selector="h1" />
<NotFound> </Found>
<PageTitle>Not found</PageTitle> <NotFound>
<LayoutView Layout="@typeof(MainLayout)"> <PageTitle>Not found</PageTitle>
<p role="alert">Sorry, there's nothing at this address.</p> <LayoutView Layout="@typeof(MainLayout)">
</LayoutView> <p role="alert">Sorry, there's nothing at this address.</p>
</NotFound> </LayoutView>
</Router> </NotFound>
</Router>
</CascadingBlazoredModal>

@ -1,19 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" /> <Content Remove="Pages\_Layout.cshtml" />
<PackageReference Include="Blazorise.Bootstrap" Version="1.4.0" /> </ItemGroup>
<PackageReference Include="Blazorise.DataGrid" Version="1.4.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.4.0" /> <ItemGroup>
<PackageReference Include="ChoETL" Version="1.2.1.64" /> <PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
<PackageReference Include="ChoETL.JSON" Version="1.2.1.64" /> <PackageReference Include="Blazored.Modal" Version="7.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Blazorise.Bootstrap" Version="1.4.0" />
</ItemGroup> <PackageReference Include="Blazorise.DataGrid" Version="1.4.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.4.0" />
</Project> <PackageReference Include="ChoETL.JSON.NETStandard" Version="1.2.1.64" />
<PackageReference Include="ChoETL.NETStandard" Version="1.2.1.64" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<UpToDateCheckInput Remove="Pages\_Layout.cshtml" />
</ItemGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="Pages\_Layout.cshtml" />
</ItemGroup>
<ItemGroup>
<None Include="Pages\_Layout.cshtml" />
</ItemGroup>
</Project>

@ -0,0 +1,12 @@
@page "/DeleteConfirmation"
<div class="simple-form">
<p>
Are you sure you want to delete @chapter.Name ?
</p>
<button @onclick="ConfirmDelete" class="btn btn-primary">Delete</button>
<button @onclick="Cancel" class="btn btn-secondary">Cancel</button>
</div>

@ -0,0 +1,38 @@
using Blazor.Services;
using Blazored.Modal.Services;
using Blazored.Modal;
using Microsoft.AspNetCore.Components;
using Blazor.ViewClasses;
namespace Blazor.Modals
{
public partial class DeleteConfirmation
{
[CascadingParameter]
public BlazoredModalInstance ModalInstance { get; set; }
[Inject]
public IDataService DataService { get; set; }
[Parameter]
public int Id { get; set; }
private Chapter chapter = new Chapter();
protected override async Task OnInitializedAsync()
{
// Get the chapter
chapter = await DataService.GetById(Id);
}
void ConfirmDelete()
{
ModalInstance.CloseAsync(ModalResult.Ok(true));
}
void Cancel()
{
ModalInstance.CancelAsync();
}
}
}

@ -1,30 +1,32 @@
@page "/chapters" @page "/chapters"
@using Blazor.ViewClasses; @using Blazor.ViewClasses;
@using Blazorise.DataGrid @using Blazorise.DataGrid
<h3>Chapters</h3> @using Blazored.Modal;
<h3>Chapters</h3>
<div>
<NavLink class="btn btn-primary" href="addChapter" Match="NavLinkMatch.All"> <div>
<i class="fa fa-plus"></i> Ajouter <NavLink class="btn btn-primary" href="addChapter" Match="NavLinkMatch.All">
</NavLink> <i class="fa fa-plus"></i> Ajouter
<NavLink class="btn btn-primary" @onclick="Export"> </NavLink>
<i class="fa fa-plus"></i> Exporter <NavLink class="btn btn-primary" @onclick="Export">
</NavLink> <i class="fa fa-plus"></i> Exporter
</div> </NavLink>
</div>
<DataGrid TItem="Chapter"
Data="@chapters" <DataGrid TItem="Chapter"
ReadData="@OnReadData" Data="@chapters"
TotalItems="@totalChapter" ReadData="@OnReadData"
PageSize="10" TotalItems="@totalChapter"
ShowPager PageSize="10"
Responsive> ShowPager
<DataGridColumn TItem="Chapter" Field="@nameof(Chapter.Id)" Caption="#" /> Responsive>
<DataGridColumn TItem="Chapter" Field="@nameof(Chapter.Name)" Caption="Display name" /> <DataGridColumn TItem="Chapter" Field="@nameof(Chapter.Id)" Caption="#" />
<DataGridColumn TItem="Chapter" Field="@nameof(Chapter.Id)" Caption="Action"> <DataGridColumn TItem="Chapter" Field="@nameof(Chapter.Name)" Caption="Display name" />
<DisplayTemplate> <DataGridColumn TItem="Chapter" Field="@nameof(Chapter.Id)" Caption="Action">
<a href="editChapter/@(context.Id)" class="btn btn-primary"><i class="fa fa-edit"></i> Editer</a> <DisplayTemplate>
</DisplayTemplate> <a href="editChapter/@(context.Id)" class="btn btn-primary"><i class="fa fa-edit"></i> Editer</a>
</DataGridColumn> <button type="button" class="btn btn-primary" @onclick="() => OnDelete(context.Id)"><i class="fa fa-trash"></i> Supprimer</button>
</DataGrid> </DisplayTemplate>
</DataGridColumn>
</DataGrid>
<script src="Pages/Chapters.razor.js"></script> <script src="Pages/Chapters.razor.js"></script>

@ -1,91 +1,119 @@
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Blazorise; using Blazor.Services;
using Blazor.Services; using Blazor.Modals;
using Blazorise.DataGrid; using Blazored.Modal;
using ChoETL; using Blazored.Modal.Services;
using Microsoft.AspNetCore.Components; using Blazor.ViewClasses;
using Microsoft.JSInterop; using System.Text;
using System.Text; using Microsoft.JSInterop;
using Blazor.ViewClasses; using Microsoft.AspNetCore.Components;
using Blazorise.DataGrid;
namespace Blazor.Pages; using ChoETL;
public partial class Chapters
{
public List<Chapter> chapters; namespace Blazor.Pages;
public partial class Chapters
private int totalChapter; {
public List<Chapter> chapters;
[Inject]
public IDataService DataService { get; set; } private int totalChapter;
public IWebHostEnvironment WebHostEnvironment { get; set; }
[Inject]
[Inject] public NavigationManager NavigationManager { get; set; }
public HttpClient Http { get; set; }
[CascadingParameter]
[Inject] public IModalService Modal { get; set; }
public ILocalStorageService LocalStorage { get; set; }
[Inject]
[Inject] public IDataService DataService { get; set; }
public NavigationManager NavigationManager { get; set; } public IWebHostEnvironment WebHostEnvironment { get; set; }
[Inject] [Inject]
public IJSRuntime IJSRuntime { get; set; } public HttpClient Http { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender) [Inject]
{ public ILocalStorageService LocalStorage { get; set; }
// Do not treat this action if is not the first render
if (!firstRender) [Inject]
{ public IJSRuntime IJSRuntime { get; set; }
return;
} protected override async Task OnAfterRenderAsync(bool firstRender)
{
var currentData = await LocalStorage.GetItemAsync<Chapter[]>("data"); // Do not treat this action if is not the first render
if (!firstRender)
// Check if data exist in the local storage {
if (currentData == null) return;
{ }
// this code add in the local storage the fake data (we load the data sync for initialize the data before load the OnReadData method)
var originalData = Http.GetFromJsonAsync<Chapter[]>($"https://trusting-panini.87-106-126-109.plesk.page/api/chapters").Result; var currentData = await LocalStorage.GetItemAsync<Chapter[]>("data");
await LocalStorage.SetItemAsync("data", originalData);
} // Check if data exist in the local storage
} if (currentData == null)
{
private async Task OnReadData(DataGridReadDataEventArgs<Chapter> e) // this code add in the local storage the fake data (we load the data sync for initialize the data before load the OnReadData method)
{ var originalData = Http.GetFromJsonAsync<Chapter[]>($"https://trusting-panini.87-106-126-109.plesk.page/api/chapters").Result;
if (e.CancellationToken.IsCancellationRequested) await LocalStorage.SetItemAsync("data", originalData);
{ }
return; }
}
private async Task OnReadData(DataGridReadDataEventArgs<Chapter> e)
// When you use a real API, we use this follow code {
//var response = await Http.GetFromJsonAsync<ChaptersModel[]>( $"https://trusting-panini.87-106-126-109.plesk.page/api/chapters?page={e.Page}&pageSize={e.PageSize}" ); if (e.CancellationToken.IsCancellationRequested)
var response = Http.GetFromJsonAsync<Chapter[]>($"https://trusting-panini.87-106-126-109.plesk.page/api/chapters").Result; {
return;
if (!e.CancellationToken.IsCancellationRequested) }
{
totalChapter = (await LocalStorage.GetItemAsync<List<Chapter>>("data")).Count; // When you use a real API, we use this follow code
chapters = new List<Chapter>(response); // an actual data for the current page //var response = await Http.GetFromJsonAsync<ChaptersModel[]>( $"https://trusting-panini.87-106-126-109.plesk.page/api/chapters?page={e.Page}&pageSize={e.PageSize}" );
} var response = Http.GetFromJsonAsync<Chapter[]>($"https://trusting-panini.87-106-126-109.plesk.page/api/chapters").Result;
}
if (!e.CancellationToken.IsCancellationRequested)
private async void Export() {
{ totalChapter = (await LocalStorage.GetItemAsync<List<Chapter>>("data")).Count;
StringBuilder sb = new StringBuilder(); chapters = new List<Chapter>(response); // an actual data for the current page
HttpResponseMessage response = await Http.GetAsync("https://trusting-panini.87-106-126-109.plesk.page/api/chapters"); }
var json = await response.Content.ReadAsStringAsync(); }
using (var jsonFile = ChoJSONReader.LoadText(json))
{ private async void Export()
using (var csvFile = new ChoCSVWriter(sb).WithFirstLineHeader()) {
{ StringBuilder sb = new StringBuilder();
csvFile.Write(jsonFile); HttpResponseMessage response = await Http.GetAsync("https://trusting-panini.87-106-126-109.plesk.page/api/chapters");
} var json = await response.Content.ReadAsStringAsync();
} using (var jsonFile = ChoJSONReader.LoadText(json))
{
var sentFile = new MemoryStream(Encoding.UTF32.GetBytes(sb.ToString())); using (var csvFile = new ChoCSVWriter(sb).WithFirstLineHeader())
{
using (var streamRef = new DotNetStreamReference(stream: sentFile)) csvFile.Write(jsonFile);
{ }
await IJSRuntime.InvokeVoidAsync("downloadFileFromStream", "data.csv", streamRef); }
}
} var sentFile = new MemoryStream(Encoding.UTF32.GetBytes(sb.ToString()));
}
using (var streamRef = new DotNetStreamReference(stream: sentFile))
{
await IJSRuntime.InvokeVoidAsync("downloadFileFromStream", "data.csv", streamRef);
}
}
private async void OnDelete(int id)
{
var parameters = new ModalParameters();
parameters.Add(nameof(Chapter.Id), id);
var modal = Modal.Show<DeleteConfirmation>("Delete Confirmation", parameters);
var result = modal.Result;
if (result.IsCanceled)
{
return;
}
await DataService.Delete(id);
// Reload the page
NavigationManager.NavigateTo("chapters", true);
}
}

@ -0,0 +1,16 @@
<html>
<body>
<link href="_content/Blazored.Modal/blazored-modal.css" rel="stylesheet" />
<script src="_content/Blazored.Modal/blazored.modal.js"></script>
<script src="_framework/blazor.server.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css">
<link href="_content/Blazorise/blazorise.css" rel="stylesheet" />
<link href="_content/Blazorise.Bootstrap/blazorise.bootstrap.css" rel="stylesheet" />
</body>
</html>

@ -6,6 +6,7 @@ using Blazorise.Bootstrap;
using Blazorise.Icons.FontAwesome; using Blazorise.Icons.FontAwesome;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Blazored.Modal;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -30,6 +31,9 @@ builder.Services
builder.Services.AddBlazoredLocalStorage(); builder.Services.AddBlazoredLocalStorage();
builder.Services.AddBlazoredModal();
builder.Services.AddScoped<IDataService, DataLocalService>(); builder.Services.AddScoped<IDataService, DataLocalService>();
var app = builder.Build(); var app = builder.Build();

@ -83,6 +83,22 @@ namespace Blazor.Services
await _localStorage.SetItemAsync("data", currentData); await _localStorage.SetItemAsync("data", currentData);
} }
public async Task Delete(int id)
{
// Get the current data
var currentData = await _localStorage.GetItemAsync<List<Chapter>>("data");
// Get the chapter int the list
var chapter = currentData.FirstOrDefault(w => w.Id == id);
// Delete chapter in
currentData.Remove(chapter);
// Save the data
await _localStorage.SetItemAsync("data", currentData);
}
public async Task<int> Count() public async Task<int> Count()
{ {

@ -23,5 +23,7 @@ namespace Blazor.Services
Task<int> CountAdmin(); Task<int> CountAdmin();
Task<List<Administrator>> ListAdmin(int currentPage, int pageSize); Task<List<Administrator>> ListAdmin(int currentPage, int pageSize);
Task Delete(int id);
} }
} }

@ -9,3 +9,6 @@
@using Blazor @using Blazor
@using Blazor.Shared @using Blazor.Shared
@using Blazorise.DataGrid @using Blazorise.DataGrid
@using Blazored.Modal
@using Blazored.Modal.Services

Loading…
Cancel
Save