| <ItemGroup> | <ItemGroup> | ||||
| <PackageReference Include="BlazorAnimate" Version="3.0.0" /> | <PackageReference Include="BlazorAnimate" Version="3.0.0" /> | ||||
| <PackageReference Include="MatBlazor" Version="2.8.0" /> | |||||
| <PackageReference Include="MatBlazor" Version="2.9.0-develop-042" /> | |||||
| <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.7" /> | <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.7" /> | ||||
| <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.7" PrivateAssets="all" /> | <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.7" PrivateAssets="all" /> | ||||
| <PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.7" /> | <PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.7" /> | ||||
| <PackageReference Include="System.Net.Http.Json" Version="5.0.0" /> | <PackageReference Include="System.Net.Http.Json" Version="5.0.0" /> | ||||
| <PackageReference Include="Tewr.Blazor.FileReader" Version="3.1.0.21158" /> | |||||
| <!--<PackageReference Include="Tewr.Blazor.FileReader" Version="3.1.0.21158" />--> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> |
| @inject PageHistoryManager PageHistoryManager | @inject PageHistoryManager PageHistoryManager | ||||
| @inject MasterDataService MasterDataService | @inject MasterDataService MasterDataService | ||||
| @inject IMatToaster Toaster | @inject IMatToaster Toaster | ||||
| @inject IJSRuntime JS | |||||
| <div class="row px-3 h-100"> | <div class="row px-3 h-100"> | ||||
| </MatRipple> | </MatRipple> | ||||
| </div> | </div> | ||||
| <div style="margin-top:1rem"> | <div style="margin-top:1rem"> | ||||
| @* <input @ref="inputTypeFileElement" class="inputFile" id="file" type="file" name="file" accept="image/x-png,image/jpeg,image/gif" @onchange="ReadFile" />*@ | |||||
| <InputFile class="inputFile" id="file" type="file" name="file" accept="image/x-png,image/jpeg,image/gif" OnChange="@OnGatheringPicture" /> | <InputFile class="inputFile" id="file" type="file" name="file" accept="image/x-png,image/jpeg,image/gif" OnChange="@OnGatheringPicture" /> | ||||
| <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default"> | <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default"> | ||||
| <label for="file"> | <label for="file"> | ||||
| </MatSelectValue> | </MatSelectValue> | ||||
| </div> | </div> | ||||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-4-desktop"> | <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-4-desktop"> | ||||
| <MatStringField Class="w-100 form-check-label" Label="@i18n["Brand"]" Outlined="true" type="text"></MatStringField> | |||||
| <div class="outlined"> | |||||
| <MatAutocompleteList TItem="Brand" FullWidth="true" Label="@i18n["Brand"]" Items="@Brands" @bind-Value="selectedBrand" CustomStringSelector="@(i => i?.Name)"> | |||||
| <ItemTemplate> | |||||
| <div> | |||||
| <span>@context?.Name</span> | |||||
| </div> | |||||
| </ItemTemplate> | |||||
| </MatAutocompleteList> | |||||
| </div> | |||||
| @*<div style="display: inline-flex; width: 100%"> | |||||
| <MatStringField Class="w-100 form-check-label" Label="@i18n["Brand"]" Outlined="true" type="text"></MatStringField> | |||||
| <MatSelectValue Class="icon-only" Outlined="true" @bind-Value="selectedBrand" Items="@Brands" ValueSelector="@(i=>i)" > | |||||
| <ItemTemplate> | |||||
| <div> | |||||
| <span>@context?.Name</span> | |||||
| </div> | |||||
| </ItemTemplate> | |||||
| </MatSelectValue> | |||||
| </div>*@ | |||||
| </div> | </div> | ||||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-4-desktop"> | <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-4-desktop"> | ||||
| <MatSelectValue FullWidth="true" Outlined="true" Label="@i18n["Type"]" @bind-Value="selectedBcType" Items="@BicycleTypes" ValueSelector="@(i=>i)"> | <MatSelectValue FullWidth="true" Outlined="true" Label="@i18n["Type"]" @bind-Value="selectedBcType" Items="@BicycleTypes" ValueSelector="@(i=>i)"> | ||||
| <ItemTemplate> | <ItemTemplate> | ||||
| <div> | <div> | ||||
| <span>@i18n["Bike." + @context?.Type]</span> | |||||
| <span>@context?.Type</span> | |||||
| </div> | </div> | ||||
| </ItemTemplate> | </ItemTemplate> | ||||
| </MatSelectValue> | </MatSelectValue> | ||||
| [Parameter] | [Parameter] | ||||
| public string FromRoute { get; set; } | public string FromRoute { get; set; } | ||||
| [Parameter(CaptureUnmatchedValues = true)] | |||||
| public IDictionary<string, object> Attributes { get; set; } | |||||
| private static long MAX_FILE_SIZE = 3145728; //3MB | private static long MAX_FILE_SIZE = 3145728; //3MB | ||||
| private ColorItem selectedColor; | private ColorItem selectedColor; | ||||
| private BicycleType selectedBcType; | private BicycleType selectedBcType; | ||||
| private ElementReference inputTypeFileElement; | |||||
| private Brand selectedBrand; | |||||
| // private ElementReference inputTypeFileElement; | |||||
| private string imgUrl = string.Empty; | private string imgUrl = string.Empty; | ||||
| private Boolean loading = false; | private Boolean loading = false; | ||||
| await GetColors(); | await GetColors(); | ||||
| await GetBicycleTypes(); | await GetBicycleTypes(); | ||||
| await GetBrands(); | |||||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | ||||
| base.OnInitialized(); | base.OnInitialized(); | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| private async Task GetBrands() { | |||||
| await InvokeAsync(async () => { | |||||
| await MasterDataService.GetBrands(); | |||||
| StateHasChanged(); | |||||
| }); | |||||
| } | |||||
| private ColorItem[] Colors { | private ColorItem[] Colors { | ||||
| get => MasterDataService.Colors; | get => MasterDataService.Colors; | ||||
| } | } | ||||
| get => MasterDataService.BicycleTypes; | get => MasterDataService.BicycleTypes; | ||||
| } | } | ||||
| private Brand[] Brands { | |||||
| get => MasterDataService.Brands; | |||||
| } | |||||
| private void Next() { | private void Next() { | ||||
| NavigationManager.NavigateTo("fundvelo/account/" + @FromRoute); | NavigationManager.NavigateTo("fundvelo/account/" + @FromRoute); | ||||
| } | } | ||||
| private async Task OnGatheringPicture(InputFileChangeEventArgs e) { | private async Task OnGatheringPicture(InputFileChangeEventArgs e) { | ||||
| IBrowserFile imgFile = e.File; | IBrowserFile imgFile = e.File; | ||||
| var buffers = new byte[imgFile.Size]; | |||||
| var buffer = new byte[imgFile.Size]; | |||||
| imgUrl = string.Empty; | |||||
| loading = true; | |||||
| StateHasChanged(); | |||||
| try { | try { | ||||
| imgUrl = string.Empty; | |||||
| loading = true; | |||||
| StateHasChanged(); | |||||
| await imgFile.OpenReadStream(MAX_FILE_SIZE).ReadAsync(buffers); | |||||
| string imageType = imgFile.ContentType; | |||||
| imgUrl = $"data:{imageType};base64,{Convert.ToBase64String(buffers)}"; | |||||
| //string text = new(await JS.InvokeAsync<string>("LoadFile", e)); | |||||
| //imgUrl = text; | |||||
| using (var stream = imgFile.OpenReadStream(MAX_FILE_SIZE)) { | |||||
| await stream.ReadAsync(buffer); | |||||
| imgUrl = $"data:{imgFile.ContentType};base64,{Convert.ToBase64String(buffer)}"; | |||||
| await stream.DisposeAsync(); | |||||
| } | |||||
| } catch (IOException ex) { | } catch (IOException ex) { | ||||
| Console.WriteLine("Ex.Meesage is: {0}.", ex.Message); | |||||
| Show(MatToastType.Danger, i18n.GetString("Error.PhotoOrPictureToBig.Title"), i18n.GetString("Error.PhotoOrPictureToBig.Msg", MAX_FILE_SIZE / (1024 * 1024))); | |||||
| Console.WriteLine("Ex.Message is: {0}.", ex.Message); | |||||
| if (ex.Message.Contains("exceeds the maximum of")) { | |||||
| Show(MatToastType.Danger, i18n.GetString("Error.PhotoOrPictureToBig.Title"), i18n.GetString("Error.PhotoOrPictureToBig.Msg", MAX_FILE_SIZE / (1024 * 1024))); | |||||
| } else { | |||||
| Show(MatToastType.Danger, i18n.GetString("Error.IOException.Title"), i18n.GetString("Error.IOException.Msg")); | |||||
| } | |||||
| } catch (JSException ex) { | |||||
| Console.WriteLine("Ex.Message is: {0}.", ex.Message); | |||||
| } finally { | } finally { | ||||
| Array.Clear(buffer, 0, buffer.Length); | |||||
| buffer = null; | |||||
| loading = false; | loading = false; | ||||
| StateHasChanged(); | StateHasChanged(); | ||||
| } | } | ||||
| } | } | ||||
| //public async Task ReadFile() { | |||||
| // foreach (var file in await fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync()) { | |||||
| // IFileInfo fileInfo = await file.ReadFileInfoAsync(); | |||||
| public void Show(MatToastType type, string title, string message, string icon = "") { | |||||
| Toaster.Add(message, type, title, icon); | |||||
| } | |||||
| // if (fileInfo.Size > MAX_FILE_SIZE) { | |||||
| //private async Task OnGatheringPicture(InputFileChangeEventArgs e) { | |||||
| // //public async Task ReadFile() { | |||||
| // //foreach (var file in await fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync()) { | |||||
| // //IFileInfo fileInfo = await file.ReadFileInfoAsync(); | |||||
| // Show(MatToastType.Danger, i18n.GetString("Error.PhotoOrPictureToBig.Title"), i18n.GetString("Error.PhotoOrPictureToBig.Msg", MAX_FILE_SIZE / (1024*1024))); | |||||
| // IBrowserFile imgFile = e.File; | |||||
| // //IFileInfo fileInfo = await imgFile.ReadFileInfoAsync(); | |||||
| // } else { | |||||
| // imgUrl = string.Empty; | |||||
| // loading = true; | |||||
| // StateHasChanged(); | |||||
| // if (fileInfo.Size > MAX_FILE_SIZE) { | |||||
| // Show(MatToastType.Danger, i18n.GetString("Error.PhotoOrPictureToBig.Title"), i18n.GetString("Error.PhotoOrPictureToBig.Msg", MAX_FILE_SIZE / (1024 * 1024))); | |||||
| // byte[] buffer = new byte[fileInfo.Size]; | |||||
| // } else { | |||||
| // imgUrl = string.Empty; | |||||
| // loading = true; | |||||
| // StateHasChanged(); | |||||
| // await using (Stream stream = await file.OpenReadAsync()) { | |||||
| // buffer = new Byte[stream.Length]; | |||||
| // await stream.ReadAsync(buffer); | |||||
| // } | |||||
| // byte[] buffer = new byte[fileInfo.Size]; | |||||
| // using (MemoryStream memoryStream = await file.CreateMemoryStreamAsync(4096)) { | |||||
| // memoryStream.Read(buffer); | |||||
| // string imageType = fileInfo.Type; | |||||
| // loading = false; | |||||
| // imgUrl = $"data:{imageType};base64,{Convert.ToBase64String(buffer)}"; | |||||
| // StateHasChanged(); | |||||
| // } | |||||
| // await using (Stream stream = await imgFile.OpenReadAsync()) { | |||||
| // buffer = new Byte[stream.Length]; | |||||
| // await stream.ReadAsync(buffer); | |||||
| // } | // } | ||||
| // using (MemoryStream memoryStream = await imgFile.CreateMemoryStreamAsync(4096)) { | |||||
| // memoryStream.Read(buffer); | |||||
| // string imageType = fileInfo.Type; | |||||
| // loading = false; | |||||
| // imgUrl = $"data:{imageType};base64,{Convert.ToBase64String(buffer)}"; | |||||
| // StateHasChanged(); | |||||
| // } | |||||
| // //} | |||||
| // } | // } | ||||
| //} | //} | ||||
| public void Show(MatToastType type, string title, string message, string icon = "") { | |||||
| Toaster.Add(message, type, title, icon); | |||||
| } | |||||
| } | |||||
| } |
| } | } | ||||
| private async void ShowCaritasWebpage() { | private async void ShowCaritasWebpage() { | ||||
| await JSRuntime.InvokeAsync<string>("open", $"https://www.caritas.ch", "_blank"); | |||||
| await JSRuntime.InvokeAsync<string>("open", $"https://www.caritas.ch", "_blank", "noopener"); | |||||
| } | } | ||||
| } | } |
| using System; | using System; | ||||
| using System.Net.Http; | using System.Net.Http; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Tewr.Blazor.FileReader; | |||||
| namespace CaritasPWA { | namespace CaritasPWA { | ||||
| builder.RootComponents.Add<App>("app"); | builder.RootComponents.Add<App>("app"); | ||||
| builder.Services.AddMatBlazor(); | builder.Services.AddMatBlazor(); | ||||
| builder.Services.AddFileReaderService(options => options.UseWasmSharedBuffer = true); | |||||
| builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); | builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); | ||||
| builder.Services.AddSingleton<ILFBicycleRest, LFBicycleRest>(); | builder.Services.AddSingleton<ILFBicycleRest, LFBicycleRest>(); | ||||
| builder.Services.AddSingleton<AppState>(); | builder.Services.AddSingleton<AppState>(); |
| namespace CaritasPWA.Shared.Models { | namespace CaritasPWA.Shared.Models { | ||||
| public class BicycleType { | public class BicycleType { | ||||
| public int Index { get; set; } | |||||
| public int Id { get; set; } | |||||
| public string Type { get; set; } | public string Type { get; set; } | ||||
| public BicycleType() { } | public BicycleType() { } | ||||
| public BicycleType(int index, string type) { | |||||
| Index = index; | |||||
| public BicycleType(int id, string type) { | |||||
| Id = id; | |||||
| Type = type; | Type = type; | ||||
| } | } | ||||
| } | } |
| namespace CaritasPWA.Shared.Models { | |||||
| public class Brand { | |||||
| public int Id { get; set; } | |||||
| public string Name { get; set; } | |||||
| public Brand() { } | |||||
| public Brand(int id, string name) { | |||||
| Id = id; | |||||
| Name = name; | |||||
| } | |||||
| } | |||||
| } |
| namespace CaritasPWA.Shared.Models { | namespace CaritasPWA.Shared.Models { | ||||
| public class Defaults { | public class Defaults { | ||||
| public static ColorItem[] ColorItems = { | |||||
| public static readonly ColorItem[] ColorItems = { | |||||
| new ColorItem(3, "Blue","0,0,255"), | new ColorItem(3, "Blue","0,0,255"), | ||||
| new ColorItem(14, "Brown", "165,42,42"), | new ColorItem(14, "Brown", "165,42,42"), | ||||
| new ColorItem(4, "Yellow", "255, 255, 0"), | new ColorItem(4, "Yellow", "255, 255, 0"), | ||||
| new ColorItem(7, "White", "255, 255, 255"), | new ColorItem(7, "White", "255, 255, 255"), | ||||
| }; | }; | ||||
| public static BicycleType[] BycicleTypes = { | |||||
| public static readonly BicycleType[] BycicleTypes = { | |||||
| new BicycleType(1, "Men_Bycicle"), | new BicycleType(1, "Men_Bycicle"), | ||||
| new BicycleType(2, "Women_Bycicle"), | new BicycleType(2, "Women_Bycicle"), | ||||
| new BicycleType(3, "Child_Bycicle"), | new BicycleType(3, "Child_Bycicle"), | ||||
| new BicycleType(7, "Tandem"), | new BicycleType(7, "Tandem"), | ||||
| new BicycleType(8, "Trailer") | new BicycleType(8, "Trailer") | ||||
| }; | }; | ||||
| public static readonly Brand[] Brands = { | |||||
| new Brand(1, "Mondia"), | |||||
| new Brand(2, "Leopard"), | |||||
| new Brand(3, "Cilo"), | |||||
| new Brand(4, "Kettler") | |||||
| }; | |||||
| } | } | ||||
| } | } | ||||
| <MatAppBarTitle Class="navBar-title">@LocationUrl</MatAppBarTitle> | <MatAppBarTitle Class="navBar-title">@LocationUrl</MatAppBarTitle> | ||||
| </MatAppBarSection> | </MatAppBarSection> | ||||
| <MatAppBarSection align="@MatAppBarSectionAlign.End" Style="max-width:min-content"> | <MatAppBarSection align="@MatAppBarSectionAlign.End" Style="max-width:min-content"> | ||||
| <NavLink target="_blank" class="text-white small" href="https://www.caritas.ch" align="@MatAppBarSectionAlign.End" style="padding-right:1em">@i18n["Learnmore"]</NavLink> | |||||
| <NavLink rel="noopener" target="_blank" class="text-white small" href="https://www.caritas.ch" align="@MatAppBarSectionAlign.End" style="padding-right:1em">@i18n["Learnmore"]</NavLink> | |||||
| </MatAppBarSection> | </MatAppBarSection> | ||||
| </MatAppBarRow> | </MatAppBarRow> | ||||
| </MatAppBar> | </MatAppBar> |
| <data name="DevelopedBy" xml:space="preserve"> | <data name="DevelopedBy" xml:space="preserve"> | ||||
| <value>Entwickelt durch</value> | <value>Entwickelt durch</value> | ||||
| </data> | </data> | ||||
| <data name="Error.IOException.Msg" xml:space="preserve"> | |||||
| <value>Die Datei konnte nicht gelesen werden.</value> | |||||
| </data> | |||||
| <data name="Error.IOException.Title" xml:space="preserve"> | |||||
| <value>Fehler beim Lesen der Datei!</value> | |||||
| </data> | |||||
| <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | ||||
| <value>Die Grösse des gewählten Bildes oder Fotos darf {0:d} MB nicht überschreiten!</value> | <value>Die Grösse des gewählten Bildes oder Fotos darf {0:d} MB nicht überschreiten!</value> | ||||
| </data> | </data> |
| <data name="DevelopedBy" xml:space="preserve"> | <data name="DevelopedBy" xml:space="preserve"> | ||||
| <value>Développé par</value> | <value>Développé par</value> | ||||
| </data> | </data> | ||||
| <data name="Error.IOException.Msg" xml:space="preserve"> | |||||
| <value>The file could not be read.</value> | |||||
| </data> | |||||
| <data name="Error.IOException.Title" xml:space="preserve"> | |||||
| <value>Error while reading file!</value> | |||||
| </data> | |||||
| <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | ||||
| <value>La taille de l'image sélectionnée ou de la photo prise dépasse la taille maximale autorisée de {0:d} MB.</value> | <value>La taille de l'image sélectionnée ou de la photo prise dépasse la taille maximale autorisée de {0:d} MB.</value> | ||||
| </data> | </data> |
| <data name="DevelopedBy" xml:space="preserve"> | <data name="DevelopedBy" xml:space="preserve"> | ||||
| <value>Sviluppata da</value> | <value>Sviluppata da</value> | ||||
| </data> | </data> | ||||
| <data name="Error.IOException.Msg" xml:space="preserve"> | |||||
| <value>Il file non ha potuto essere caricato.</value> | |||||
| </data> | |||||
| <data name="Error.IOException.Title" xml:space="preserve"> | |||||
| <value>Errore!</value> | |||||
| </data> | |||||
| <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | ||||
| <value>La dimensione dell'immagine selezionata o della foto scattata supera la dimensione massima consentita di {0:d} MB.</value> | <value>La dimensione dell'immagine selezionata o della foto scattata supera la dimensione massima consentita di {0:d} MB.</value> | ||||
| </data> | </data> |
| <data name="DevelopedBy" xml:space="preserve"> | <data name="DevelopedBy" xml:space="preserve"> | ||||
| <value>Developed by</value> | <value>Developed by</value> | ||||
| </data> | </data> | ||||
| <data name="Error.IOException.Msg" xml:space="preserve"> | |||||
| <value>The file could not be read.</value> | |||||
| </data> | |||||
| <data name="Error.IOException.Title" xml:space="preserve"> | |||||
| <value>Error while reading file!</value> | |||||
| </data> | |||||
| <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | <data name="Error.PhotoOrPictureToBig.Msg" xml:space="preserve"> | ||||
| <value>The size of the selected picture or taken photo exceeds the max. allowed size of {0:d} MB.</value> | <value>The size of the selected picture or taken photo exceeds the max. allowed size of {0:d} MB.</value> | ||||
| </data> | </data> |
| List<ColorItem> GetColors(); | List<ColorItem> GetColors(); | ||||
| List<BicycleType> GetBicycleTypes(); | List<BicycleType> GetBicycleTypes(); | ||||
| List<Brand> GetBrands(); | |||||
| } | } | ||||
| } | } |
| using CaritasPWA.Shared.Models; | using CaritasPWA.Shared.Models; | ||||
| using CaritasPWA.Shared.ResourceFiles; | |||||
| using Microsoft.Extensions.Localization; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | using System.Linq; | ||||
| // REST interface responsible to submit lost or found reports and get the available masterdata. | // REST interface responsible to submit lost or found reports and get the available masterdata. | ||||
| public class LFBicycleRest : ILFBicycleRest { | public class LFBicycleRest : ILFBicycleRest { | ||||
| private readonly IStringLocalizer<Resources> _i18n; | |||||
| public LFBicycleRest(IStringLocalizer<Resources> i18n) { | |||||
| _i18n = i18n; | |||||
| } | |||||
| public List<ColorItem> GetColors() { | public List<ColorItem> GetColors() { | ||||
| //return Defaults.ColorItems.ToList(); | //return Defaults.ColorItems.ToList(); | ||||
| return new List<ColorItem>(); | return new List<ColorItem>(); | ||||
| } | } | ||||
| public List<BicycleType> GetBicycleTypes() { | public List<BicycleType> GetBicycleTypes() { | ||||
| return Defaults.BycicleTypes.ToList(); | |||||
| List<BicycleType> bicycleTypes = new (); | |||||
| foreach (BicycleType bct in Defaults.BycicleTypes) { | |||||
| bicycleTypes.Add(new BicycleType(bct.Id, _i18n.GetString("Bike." + bct.Type))); | |||||
| } | |||||
| return bicycleTypes; | |||||
| //return new List<BicycleType>(); | //return new List<BicycleType>(); | ||||
| } | } | ||||
| public List<Brand> GetBrands() { | |||||
| return Defaults.Brands.ToList(); | |||||
| //return new List<BicycleType>(); | |||||
| } | |||||
| } | } | ||||
| } | } |
| namespace CaritasPWA.Shared.Services { | namespace CaritasPWA.Shared.Services { | ||||
| public class MasterDataService { | public class MasterDataService { | ||||
| private ILFBicycleRest _lFBicycleRest; | |||||
| private readonly ILFBicycleRest _lFBicycleRest; | |||||
| private const string KeyNameColors = "colors"; | private const string KeyNameColors = "colors"; | ||||
| private const string KeyNameBcTypes = "bicycleTypes"; | private const string KeyNameBcTypes = "bicycleTypes"; | ||||
| private const string KeyNameBrands = "brands"; | |||||
| private readonly IJSRuntime _jsRuntime; | private readonly IJSRuntime _jsRuntime; | ||||
| private bool _initializedColors; | private bool _initializedColors; | ||||
| private bool _initializedBcTypes; | private bool _initializedBcTypes; | ||||
| private ColorItem[] _colors = new ColorItem[] { }; | |||||
| private BicycleType[] _bicycleTypes = new BicycleType[] { }; | |||||
| private bool _initializedBrands; | |||||
| private ColorItem[] _colors; | |||||
| private BicycleType[] _bicycleTypes; | |||||
| private Brand[] _brands; | |||||
| public ColorItem[] Colors { | public ColorItem[] Colors { | ||||
| get => _colors; | get => _colors; | ||||
| set => _bicycleTypes = value; | set => _bicycleTypes = value; | ||||
| } | } | ||||
| public Brand[] Brands { | |||||
| get => _brands; | |||||
| set => _brands = value; | |||||
| } | |||||
| public event EventHandler Changed; | public event EventHandler Changed; | ||||
| public MasterDataService(IJSRuntime jsRuntime, ILFBicycleRest lFBicycleRest) { | public MasterDataService(IJSRuntime jsRuntime, ILFBicycleRest lFBicycleRest) { | ||||
| public async Task SynchronizeMasterdata() { | public async Task SynchronizeMasterdata() { | ||||
| await SynchronizeColors(); | await SynchronizeColors(); | ||||
| await SynchronizeBcTypes(); | await SynchronizeBcTypes(); | ||||
| await SynchronizeBrands(); | |||||
| } | } | ||||
| public async Task SynchronizeColors() { | public async Task SynchronizeColors() { | ||||
| } | } | ||||
| } | } | ||||
| public async Task SynchronizeBrands() { | |||||
| Brands = _lFBicycleRest.GetBrands().ToArray(); | |||||
| if (Brands != null && Brands.Length > 0) { | |||||
| await SaveBrandsToStorage(); | |||||
| } | |||||
| } | |||||
| public async Task<ColorItem[]> GetColors() { | public async Task<ColorItem[]> GetColors() { | ||||
| ColorItem[] colors = await GetColorsFromStorage(); | ColorItem[] colors = await GetColorsFromStorage(); | ||||
| Colors = (colors != null && colors.Length > 0) ? colors : Defaults.ColorItems; | Colors = (colors != null && colors.Length > 0) ? colors : Defaults.ColorItems; | ||||
| return BicycleTypes; | return BicycleTypes; | ||||
| } | } | ||||
| public async Task<BicycleType[]> GetBrands() { | |||||
| Brand[] brands = await GetBrandsFromStorage(); | |||||
| Brands = (brands != null && brands.Length > 0) ? brands : Defaults.Brands; | |||||
| return BicycleTypes; | |||||
| } | |||||
| private async ValueTask<ColorItem[]> GetColorsFromStorage() { | private async ValueTask<ColorItem[]> GetColorsFromStorage() { | ||||
| // Register the Storage event handler. This handler calls OnStorageUpdated when the storage changed. | // Register the Storage event handler. This handler calls OnStorageUpdated when the storage changed. | ||||
| ColorItem[] result; | ColorItem[] result; | ||||
| var str = await _jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameColors); | var str = await _jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameColors); | ||||
| if (str != null) { | if (str != null) { | ||||
| result = System.Text.Json.JsonSerializer.Deserialize<ColorItem[]>(str) ?? new ColorItem[] { }; | |||||
| result = System.Text.Json.JsonSerializer.Deserialize<ColorItem[]>(str) ?? Array.Empty<ColorItem>(); | |||||
| } else { | } else { | ||||
| result = new ColorItem[] { }; | |||||
| result = Array.Empty<ColorItem>(); | |||||
| } | } | ||||
| _colors = result; | _colors = result; | ||||
| return result; | return result; | ||||
| BicycleType[] result; | BicycleType[] result; | ||||
| var str = await _jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameBcTypes); | var str = await _jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameBcTypes); | ||||
| if (str != null) { | if (str != null) { | ||||
| result = System.Text.Json.JsonSerializer.Deserialize<BicycleType[]>(str) ?? new BicycleType[] { }; | |||||
| result = System.Text.Json.JsonSerializer.Deserialize<BicycleType[]>(str) ?? Array.Empty<BicycleType>(); | |||||
| } else { | } else { | ||||
| result = new BicycleType[] { }; | |||||
| result = Array.Empty<BicycleType>(); | |||||
| } | } | ||||
| _bicycleTypes = result; | _bicycleTypes = result; | ||||
| return result; | return result; | ||||
| } | } | ||||
| private async ValueTask<Brand[]> GetBrandsFromStorage() { | |||||
| // Register the Storage event handler. This handler calls OnStorageUpdated when the storage changed. | |||||
| // This way, you can reload the settings when another instance of the application (tab / window) save the settings | |||||
| if (!_initializedBrands) { | |||||
| // Create a reference to the current object, so the JS function can call the public method "OnStorageUpdated" | |||||
| var reference = DotNetObjectReference.Create(this); | |||||
| await _jsRuntime.InvokeVoidAsync("BlazorRegisterStorageEvent", reference); | |||||
| _initializedBrands = true; | |||||
| } | |||||
| // Read the JSON string that contains the data from the local storage | |||||
| Brand[] result; | |||||
| var str = await _jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameBrands); | |||||
| if (str != null) { | |||||
| result = System.Text.Json.JsonSerializer.Deserialize<Brand[]>(str) ?? Array.Empty<Brand>(); | |||||
| } else { | |||||
| result = Array.Empty<Brand>(); | |||||
| } | |||||
| _brands = result; | |||||
| return result; | |||||
| } | |||||
| private async Task SaveColorsToStorage() { | private async Task SaveColorsToStorage() { | ||||
| var json = System.Text.Json.JsonSerializer.Serialize(_colors); | var json = System.Text.Json.JsonSerializer.Serialize(_colors); | ||||
| await _jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameColors, json); | await _jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameColors, json); | ||||
| await _jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameBcTypes, json); | await _jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameBcTypes, json); | ||||
| } | } | ||||
| private async Task SaveBrandsToStorage() { | |||||
| var json = System.Text.Json.JsonSerializer.Serialize(_brands); | |||||
| await _jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameBrands, json); | |||||
| } | |||||
| // This method is called from BlazorRegisterStorageEvent when the storage changed | // This method is called from BlazorRegisterStorageEvent when the storage changed | ||||
| [JSInvokable] | [JSInvokable] | ||||
| public void OnStorageUpdated(string key) { | public void OnStorageUpdated(string key) { |
| namespace CaritasPWA.Shared.Services { | namespace CaritasPWA.Shared.Services { | ||||
| public class PageHistoryManager { | public class PageHistoryManager { | ||||
| private List<string> previousPages; | |||||
| private readonly List<string> previousPages; | |||||
| public PageHistoryManager() { | public PageHistoryManager() { | ||||
| previousPages = new List<string>(); | previousPages = new List<string>(); |
| private readonly IJSRuntime _jsRuntime; | private readonly IJSRuntime _jsRuntime; | ||||
| private bool _initialized; | private bool _initialized; | ||||
| private UserData _data = new UserData(); | |||||
| private UserData _data = new (); | |||||
| public UserData Data { | public UserData Data { | ||||
| get => _data; | get => _data; |
| color: var(--primary); | color: var(--primary); | ||||
| } | } | ||||
| a:hover { | |||||
| color: var(--caritas-red-accent); | |||||
| } | |||||
| a:hover { | |||||
| color: var(--caritas-red-accent); | |||||
| } | |||||
| .inputFile { | .inputFile { | ||||
| width: 0.1px; | width: 0.1px; | ||||
| z-index: -1; | z-index: -1; | ||||
| } | } | ||||
| .inputFile + label { | |||||
| cursor: pointer; | |||||
| width: 100%; | |||||
| text-align: center; | |||||
| } | |||||
| .inputFile + label { | |||||
| cursor: pointer; | |||||
| width: 100%; | |||||
| text-align: center; | |||||
| } | |||||
| .inputfile-mat-ripple { | .inputfile-mat-ripple { | ||||
| width: 48px; | width: 48px; | ||||
| border-color: var(--caritas-red-accent); | border-color: var(--caritas-red-accent); | ||||
| } | } | ||||
| .btn-primary:hover { | |||||
| color: #fff; | |||||
| background-color: var(--primary); | |||||
| border-color: var(--caritas-red-accent); | |||||
| } | |||||
| .btn-primary:hover { | |||||
| color: #fff; | |||||
| background-color: var(--primary); | |||||
| border-color: var(--caritas-red-accent); | |||||
| } | |||||
| .btn-primary.focus, .btn-primary:focus { | |||||
| color: #fff; | |||||
| background-color: var(--caritas-red-dark); | |||||
| border-color: var(--primary); | |||||
| box-shadow: 0 0 0 .2rem rgb(255 64 88 / 0.5); | |||||
| } | |||||
| .btn-primary.focus, .btn-primary:focus { | |||||
| color: #fff; | |||||
| background-color: var(--caritas-red-dark); | |||||
| border-color: var(--primary); | |||||
| box-shadow: 0 0 0 .2rem rgb(255 64 88 / 0.5); | |||||
| } | |||||
| .btn-primary:not(:disabled):not(.disabled).active, | |||||
| .btn-primary:not(:disabled):not(.disabled):active, | |||||
| .show > .btn-primary.dropdown-toggle { | |||||
| color: #fff; | |||||
| background-color: var(--caritas-red-deep); | |||||
| border-color: var(--caritas-red-dark); | |||||
| } | |||||
| .btn-primary:not(:disabled):not(.disabled).active, | |||||
| .btn-primary:not(:disabled):not(.disabled):active, | |||||
| .show > .btn-primary.dropdown-toggle { | |||||
| color: #fff; | |||||
| background-color: var(--caritas-red-deep); | |||||
| border-color: var(--caritas-red-dark); | |||||
| } | |||||
| .text-black { | .text-black { | ||||
| color: rgba(0,0,0) !important; | color: rgba(0,0,0) !important; | ||||
| } | } | ||||
| .fv-mat-card { | .fv-mat-card { | ||||
| border-radius:20px; | |||||
| border-radius: 20px; | |||||
| } | } | ||||
| .mat-icon-large { | .mat-icon-large { | ||||
| margin-left: -5px; | margin-left: -5px; | ||||
| display: block; | display: block; | ||||
| } | } | ||||
| .fullscreen { | .fullscreen { | ||||
| width: 100vw; | width: 100vw; | ||||
| height: 100vh; | height: 100vh; | ||||
| z-index: 1000; | z-index: 1000; | ||||
| } | } | ||||
| #blazor-error-ui .dismiss { | |||||
| cursor: pointer; | |||||
| position: absolute; | |||||
| right: 0.75rem; | |||||
| top: 0.5rem; | |||||
| } | |||||
| #blazor-error-ui .dismiss { | |||||
| cursor: pointer; | |||||
| position: absolute; | |||||
| right: 0.75rem; | |||||
| top: 0.5rem; | |||||
| } | |||||
| .navBar-title { | .navBar-title { | ||||
| padding-left: 0px; | padding-left: 0px; | ||||
| -ms-transform: translate(-50%, -50%); | -ms-transform: translate(-50%, -50%); | ||||
| transform: translate(-50%, -50%); | transform: translate(-50%, -50%); | ||||
| } | } | ||||
| div.icon-only.mat-select { | |||||
| min-width: 48px; | |||||
| max-width: 48px; | |||||
| } | |||||
| div.icon-only.mat-select div.mdc-select__anchor { | |||||
| padding-left: 0; | |||||
| } | |||||
| div.icon-only.mat-select span.mdc-select_dropdown-icon { | |||||
| margin-left: 0; | |||||
| } | |||||
| .mat-autocomplete-list-popup { | |||||
| opacity: 1; | |||||
| } | |||||
| div.outlined label.mat-text-field { | |||||
| border-bottom-right-radius: 4px; | |||||
| border-bottom-left-radius: 4px; | |||||
| margin-bottom: auto; | |||||
| } | |||||
| div.outlined input.mat-text-field-input { | |||||
| border-width: 1px; | |||||
| border-style: solid; | |||||
| border-color: rgb(0 0 0 / 38%); | |||||
| border-radius: 4px; | |||||
| } | |||||
| div.outlined input.mat-text-field-input:focus { | |||||
| border-width: 2px; | |||||
| border-style: solid; | |||||
| border-color: var(--primary); | |||||
| border-radius: 4px; | |||||
| } | |||||
| div.outlined .mdc-text-field.mdc-text-field--fullwidth .mdc-floating-label.mdc-floating-label--float-above { | |||||
| transform: translateY(-172%) translateX(-8%) scale(0.75); | |||||
| background-color: white; | |||||
| z-index: 2; | |||||
| min-width: 60px; | |||||
| text-align: center; | |||||
| } | |||||
| .mat-autocomplete-list-popup { | |||||
| background-color: white; | |||||
| z-index: 5; | |||||
| } |
| const fileInput = document.getElementById('file-999'); | |||||
| fileInput.addEventListener('change', (e) => LoadFiles(e.target.files)); | |||||
| function LoadFiles(fileList) { | |||||
| let file = null; | |||||
| for (let i = 0; i < fileList.length;) { | |||||
| if (fileList[i].type.match(/^image\//)) { | |||||
| file = fileList[i]; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| <html lang="de-ch"> | <html lang="de-ch"> | ||||
| <head> | <head> | ||||
| <title>Caritas PWA</title> | |||||
| <base href="/" /> | |||||
| <meta charset="utf-8" /> | <meta charset="utf-8" /> | ||||
| <meta name="description" content="Caritas PWA, developed by INTEGRATE AG, Switzerland"> | <meta name="description" content="Caritas PWA, developed by INTEGRATE AG, Switzerland"> | ||||
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes" /> | <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes" /> | ||||
| <title>Caritas PWA</title> | |||||
| <base href="/" /> | |||||
| <meta name="apple-mobile-web-app-status-bar" content="#db001b"> | |||||
| <meta name="theme-color" content="#db001b"> | |||||
| <script src="_content/BlazorAnimate/blazorAnimateInterop.js"></script> | <script src="_content/BlazorAnimate/blazorAnimateInterop.js"></script> | ||||
| <script src="_content/MatBlazor/dist/matBlazor.js"></script> | <script src="_content/MatBlazor/dist/matBlazor.js"></script> | ||||
| <link href="_content/MatBlazor/dist/matBlazor.css" rel="stylesheet" /> | <link href="_content/MatBlazor/dist/matBlazor.css" rel="stylesheet" /> | ||||
| <link href="css/app.css" rel="stylesheet" /> | <link href="css/app.css" rel="stylesheet" /> | ||||
| <link href="manifest.json" rel="manifest" /> | <link href="manifest.json" rel="manifest" /> | ||||
| <link rel="apple-touch-icon" href="/icons/icon-60@3x.png" /> | <link rel="apple-touch-icon" href="/icons/icon-60@3x.png" /> | ||||
| <meta name="apple-mobile-web-app-status-bar" content="#db001b"> | |||||
| <meta name="theme-color" content="#db001b"> | |||||
| </head> | </head> | ||||
| <body> | <body> | ||||
| }); | }); | ||||
| } | } | ||||
| </script> | </script> | ||||
| <script> | |||||
| window.LoadFile = (evt) => { | |||||
| var tgt = evt.target || window.event.srcElement, | |||||
| files = tgt.files; | |||||
| let file = files[0]; | |||||
| file64 = URL.createObjectURL(file); | |||||
| //const reader = new FileReader(); | |||||
| //reader.onloadend = function () { | |||||
| // file64 = reader.result; | |||||
| //} | |||||
| //reader.addEventListener("load", function () { | |||||
| // file64 = reader.result; | |||||
| //}, false); | |||||
| //if (file) { | |||||
| // // reader.readAsDataURL(file); | |||||
| // read(reader); | |||||
| //} | |||||
| return file64; | |||||
| } | |||||
| async function read(reader) { | |||||
| await reader.readAsDataURL(file); | |||||
| } | |||||
| </script> | |||||
| </body> | </body> | ||||
| const staticCacheName = 'site-static-v1'; | const staticCacheName = 'site-static-v1'; | ||||
| const assets = [ | const assets = [ | ||||
| '/', | |||||
| './', | |||||
| '/index.html', | '/index.html', | ||||
| '/account', | '/account', | ||||
| '/account/Found', | '/account/Found', | ||||
| // activate event | // activate event | ||||
| self.addEventListener('activate', event => { | self.addEventListener('activate', event => { | ||||
| // delete any caches that aren't in expectedCaches | |||||
| // which will get rid of site-static-v1 | |||||
| //delete any caches that aren't in expectedCaches | |||||
| //which will get rid of site-static-v1 | |||||
| event.waitUntil( | event.waitUntil( | ||||
| caches.keys().then(keys => Promise.all( | caches.keys().then(keys => Promise.all( | ||||
| keys.map(key => { | keys.map(key => { |