| </div> | </div> | ||||
| @if (OnlineStatusProvider.Online) { | @if (OnlineStatusProvider.Online) { | ||||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-1 justify-content-center" style="text-align: center"> | <div class="mat-layout-grid-cell mat-layout-grid-cell-span-1 justify-content-center" style="text-align: center"> | ||||
| <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default" @onclick="InitializeMapPosition"> | |||||
| <label> | |||||
| <svg xmlns="http://www.w3.org/2000/svg" height="48px" width="48px" viewBox="0 0 24 24" fill="#000000"> | |||||
| <path d="M0 0h24v24H0V0z" fill="none" /> | |||||
| <path d="M13 3.06V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06c-.46-4.17-3.77-7.48-7.94-7.94zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z" /> | |||||
| <circle cx="12" cy="12" opacity=".3" r="2" /> | |||||
| <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" /> | |||||
| </svg> | |||||
| </label> | |||||
| </MatRipple> | |||||
| <div> | |||||
| <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default" @onclick="InitializeDeviceMapPosition"> | |||||
| <label> | |||||
| <svg xmlns="http://www.w3.org/2000/svg" height="48px" width="48px" viewBox="0 0 24 24" fill="#000000"> | |||||
| <path d="M0 0h24v24H0V0z" fill="none" /> | |||||
| <path d="M13 3.06V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06c-.46-4.17-3.77-7.48-7.94-7.94zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z" /> | |||||
| <circle cx="12" cy="12" opacity=".3" r="2" /> | |||||
| <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" /> | |||||
| </svg> | |||||
| </label> | |||||
| </MatRipple> | |||||
| </div> | |||||
| <div style="margin-top:1rem"> | |||||
| <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default" @onclick="InitializeBicycleMapPosition"> | |||||
| <label> | |||||
| <svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 20 20" height="48px" viewBox="0 0 20 20" width="48px" fill="#000000"> | |||||
| <g><rect fill="none" height="20" width="20" /></g> | |||||
| <g><g><path d="M15.5,9h-0.68l-1.58-4.34C13.1,4.26,12.72,4,12.3,4H10v1h2.3l1.46,4H8.75L8.38,8H10V7H6v1h1.32l1.46,4H7.95 C7.7,10.19,6.13,8.86,4.2,9.01c-1.64,0.13-3.01,1.46-3.18,3.1C0.8,14.25,2.41,16,4.5,16c1.79,0,3.21-1.29,3.45-3h4.1 c0.25,1.81,1.83,3.14,3.75,2.99c1.64-0.13,3.01-1.46,3.18-3.1C19.2,10.75,17.59,9,15.5,9z M6.95,13c-0.23,1.15-1.22,2-2.45,2 C3.1,15,2,13.9,2,12.5S3.1,10,4.5,10c1.23,0,2.23,0.85,2.45,2H4v1H6.95z M12.05,12H9.84l-0.73-2h3.92 C12.5,10.52,12.16,11.22,12.05,12z M15.5,15c-1.4,0-2.5-1.1-2.5-2.5c0-0.94,0.5-1.73,1.24-2.16l1.03,2.83l0.94-0.34l-1.02-2.8 C15.3,10.02,15.4,10,15.5,10c1.4,0,2.5,1.1,2.5,2.5S16.9,15,15.5,15z" /></g></g> | |||||
| </svg> | |||||
| </label> | |||||
| </MatRipple> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-3"> | <div class="mat-layout-grid-cell mat-layout-grid-cell-span-3"> | ||||
| <div class="w-100 fv-osm-tile map-wrapper"> | <div class="w-100 fv-osm-tile map-wrapper"> | ||||
| LatLng coordinates = new LatLng(report.GeographicInfo.Latitude, report.GeographicInfo.Longitude); | LatLng coordinates = new LatLng(report.GeographicInfo.Latitude, report.GeographicInfo.Longitude); | ||||
| MouseEvent mouseEvent = new MouseEvent(); | MouseEvent mouseEvent = new MouseEvent(); | ||||
| mouseEvent.LatLng = coordinates; | mouseEvent.LatLng = coordinates; | ||||
| await InitializeMapPosition(); | |||||
| await InitializeBicycleMapPosition(); | |||||
| await AddBicycleMarkerOnClickPosition(mouseEvent); | await AddBicycleMarkerOnClickPosition(mouseEvent); | ||||
| StateHasChanged(); | StateHasChanged(); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private void refreshGUIFromDto() { | |||||
| private async void refreshGUIFromDto() { | |||||
| FoundReport report = ReportDataProvider.GetFoundReport(); | FoundReport report = ReportDataProvider.GetFoundReport(); | ||||
| bicycleGeoPosition.Address = report.GeographicInfo.Address; | bicycleGeoPosition.Address = report.GeographicInfo.Address; | ||||
| bicycleGeoPosition.Zip = report.GeographicInfo.Postcode; | bicycleGeoPosition.Zip = report.GeographicInfo.Postcode; | ||||
| bicycleGeoPosition.City = report.GeographicInfo.Town; | bicycleGeoPosition.City = report.GeographicInfo.Town; | ||||
| bicycleGeoPosition.Latitude = report.GeographicInfo.Latitude; | bicycleGeoPosition.Latitude = report.GeographicInfo.Latitude; | ||||
| bicycleGeoPosition.Longitude = report.GeographicInfo.Longitude; | bicycleGeoPosition.Longitude = report.GeographicInfo.Longitude; | ||||
| bicycleGeoPosition.DisplayCity = await GetFormattedAddressZipAndTown(ReportDataProvider); | |||||
| imgUrl = report.FotoString; | imgUrl = report.FotoString; | ||||
| selectedColor = Array.Find(Colors, color => color.Id == report.FarbeId); | selectedColor = Array.Find(Colors, color => color.Id == report.FarbeId); | ||||
| selectedBrand = String.IsNullOrEmpty(report.NeueMarke) ? Array.Find(Brands, brand => brand.Id == report.MarkeId) : new Brand(-999, report.NeueMarke); | selectedBrand = String.IsNullOrEmpty(report.NeueMarke) ? Array.Find(Brands, brand => brand.Id == report.MarkeId) : new Brand(-999, report.NeueMarke); | ||||
| frameNumber = report.RahmenNummer; | frameNumber = report.RahmenNummer; | ||||
| remark = report.Bemerkung; | remark = report.Bemerkung; | ||||
| abholadresseIsNotContact = !report.AbholadresseIstKontakt; | abholadresseIsNotContact = !report.AbholadresseIstKontakt; | ||||
| StateHasChanged(); | |||||
| } | } | ||||
| private void updateDtoFromGUI() { | private void updateDtoFromGUI() { |
| private NominatimService NominatimService { get; set; } | private NominatimService NominatimService { get; set; } | ||||
| private static NominatimReverseAddress addressDto; | |||||
| private static NominatimReverseAddress AddressDto { get => addressDto; set { addressDto = value; } } | |||||
| private NominatimReverseAddress addressDto; | |||||
| public CaritasServiceFundVeloKeyDataPageBase() : base() { | public CaritasServiceFundVeloKeyDataPageBase() : base() { | ||||
| await this.mapRef.OnClick(async (MouseEvent mouseEvent) => await OnMouseMapClicked(mouseEvent)); | await this.mapRef.OnClick(async (MouseEvent mouseEvent) => await OnMouseMapClicked(mouseEvent)); | ||||
| } | } | ||||
| protected async Task InitializeMapPosition() { | |||||
| protected async Task InitializeDeviceMapPosition() { | |||||
| CreateBicycleMarkerOptions(); | CreateBicycleMarkerOptions(); | ||||
| await AddEventsToMap(); | await AddEventsToMap(); | ||||
| if (this.bicycleGeoPosition.Latitude == 0 && this.bicycleGeoPosition.Longitude == 0) { | |||||
| await ShowDeviceGeoLocation(); | |||||
| } else { | |||||
| await ShowBicycleGeoLocation(); | |||||
| } | |||||
| await ShowDeviceGeoLocation(); | |||||
| } | |||||
| protected async Task InitializeBicycleMapPosition() { | |||||
| CreateBicycleMarkerOptions(); | |||||
| await AddEventsToMap(); | |||||
| await ShowBicycleGeoLocation(); | |||||
| } | } | ||||
| protected async Task<string> GetFormattedAddressZipAndTown(ReportDataProvider ReportDataProvider) { | protected async Task<string> GetFormattedAddressZipAndTown(ReportDataProvider ReportDataProvider) { | ||||
| this.bicycleGeoPosition.Latitude = ReportDataProvider.GetFoundReport().GeographicInfo.Latitude; | this.bicycleGeoPosition.Latitude = ReportDataProvider.GetFoundReport().GeographicInfo.Latitude; | ||||
| this.bicycleGeoPosition.Longitude = ReportDataProvider.GetFoundReport().GeographicInfo.Longitude; | this.bicycleGeoPosition.Longitude = ReportDataProvider.GetFoundReport().GeographicInfo.Longitude; | ||||
| addressDto = await NominatimService.GetAddressForCoordinates(this.bicycleGeoPosition.Latitude, this.bicycleGeoPosition.Longitude); | addressDto = await NominatimService.GetAddressForCoordinates(this.bicycleGeoPosition.Latitude, this.bicycleGeoPosition.Longitude); | ||||
| if (addressDto == null) { | |||||
| addressDto = new(); | |||||
| addressDto.address = new(); | |||||
| addressDto.address.postcode = ReportDataProvider.GetFoundReport().GeographicInfo.Postcode; | |||||
| addressDto.address.town = ReportDataProvider.GetFoundReport().GeographicInfo.Town; | |||||
| } | |||||
| } | } | ||||
| return GetFormattedAddressZipAndTown(addressDto); | return GetFormattedAddressZipAndTown(addressDto); | ||||
| } | } | ||||
| if (this.bicycleGeoPosition.Latitude != 0 && this.bicycleGeoPosition.Longitude != 0) { | if (this.bicycleGeoPosition.Latitude != 0 && this.bicycleGeoPosition.Longitude != 0) { | ||||
| LatLng geoPosition = new(this.bicycleGeoPosition.Latitude, this.bicycleGeoPosition.Longitude); | LatLng geoPosition = new(this.bicycleGeoPosition.Latitude, this.bicycleGeoPosition.Longitude); | ||||
| if (this.devicePositionMarker != null) { | |||||
| await devicePositionMarker.Remove(); | |||||
| } | |||||
| this.devicePositionMarker = await this.MarkerFactory.CreateAndAddToMap(geoPosition, this.mapRef); | |||||
| await this.mapRef.SetZoom(16); | await this.mapRef.SetZoom(16); | ||||
| await this.mapRef.SetView(geoPosition); | await this.mapRef.SetView(geoPosition); | ||||
| } | } | ||||
| } | } | ||||
| private static string SplitAndGetFirstPostcode(string postcode) { | private static string SplitAndGetFirstPostcode(string postcode) { | ||||
| return postcode.Split("-", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)[0]; | |||||
| return String.IsNullOrEmpty(postcode)? "": postcode.Split("-", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)[0]; | |||||
| } | } | ||||
| private async Task OnMouseMapClicked(MouseEvent mouseEvent) { | private async Task OnMouseMapClicked(MouseEvent mouseEvent) { |
| @code { | @code { | ||||
| private int NbrPendingReports; | |||||
| private int NbrPendingReports = 0; | |||||
| protected async override void OnInitialized() { | protected async override void OnInitialized() { | ||||
| base.OnInitialized(); | base.OnInitialized(); | ||||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | ||||
| ReportDataProvider.Report = null; | ReportDataProvider.Report = null; | ||||
| ReportDataProvider.ReportRepositoryItem = null; | ReportDataProvider.ReportRepositoryItem = null; | ||||
| StateHasChanged(); | |||||
| NbrPendingReports = await ReportRepositoryService.GetNbrOfPendingReports(); | NbrPendingReports = await ReportRepositoryService.GetNbrOfPendingReports(); | ||||
| StateHasChanged(); | StateHasChanged(); | ||||
| } | } | ||||
| } | } | ||||
| private string getOpacity() { | private string getOpacity() { | ||||
| return NbrPendingReports > 0 ? "opacity:1.0" : "opacity:0.5"; | |||||
| return NbrPendingReports > 0 ? "opacity:1.0" : "opacity:0.5"; | |||||
| } | } | ||||
| } | } |
| @inject ReportDataProvider ReportDataProvider | @inject ReportDataProvider ReportDataProvider | ||||
| @inject ReportRepositoryService ReportRepositoryService | @inject ReportRepositoryService ReportRepositoryService | ||||
| @inject IStringLocalizer<Resources> i18n; | @inject IStringLocalizer<Resources> i18n; | ||||
| @inject Toaster Toaster; | |||||
| <div class="row px-3 h-100"> | <div class="row px-3 h-100"> | ||||
| <div class="row no-gutters align-items-start w-100" style="padding-top: 1rem;"> | <div class="row no-gutters align-items-start w-100" style="padding-top: 1rem;"> | ||||
| </div> | </div> | ||||
| <div style="padding-top: 0.8rem">@context.ID</div> | <div style="padding-top: 0.8rem">@context.ID</div> | ||||
| </td> | </td> | ||||
| <td>@translateType(context.ReportType)</td> | |||||
| <td>@ReportRepositoryService.GetCurrentDateTimeFromMillis(context.ID)</td> | |||||
| <td>@getAddress(context)</td> | |||||
| <td style="@getTypeBackgroundStyle(context.ReportType)">@translateType(context.ReportType)</td> | |||||
| <td style="white-space: nowrap">@ReportRepositoryService.GetCurrentDateTimeFromMillis(context.ID)</td> | |||||
| <td style="white-space: nowrap">@getAddress(context)</td> | |||||
| <td>@getPicture(context)</td> | <td>@getPicture(context)</td> | ||||
| <td> | <td> | ||||
| <MatIconButton Icon="delete_forever" OnClick="@(_ => DeleteReport(context))"></MatIconButton> | <MatIconButton Icon="delete_forever" OnClick="@(_ => DeleteReport(context))"></MatIconButton> | ||||
| return i18n.GetString("ReportType." + type); | return i18n.GetString("ReportType." + type); | ||||
| } | } | ||||
| private string getTypeBackgroundStyle(ReportRepositoryItem.Type type) { | |||||
| return ReportRepositoryItem.Type.FOUND.Equals(type) ? "background: linear-gradient(45deg, darkseagreen, transparent)" : "background: linear-gradient(45deg, darksalmon, transparent)"; | |||||
| } | |||||
| private string getAddress(ReportRepositoryItem item) { | private string getAddress(ReportRepositoryItem item) { | ||||
| return ReportRepositoryItem.Type.FOUND.Equals(item.ReportType) ? ((FoundReportRepositoryItem)item).Report.GeographicInfo.Address : ""; | return ReportRepositoryItem.Type.FOUND.Equals(item.ReportType) ? ((FoundReportRepositoryItem)item).Report.GeographicInfo.Address : ""; | ||||
| } | } | ||||
| return ""; | return ""; | ||||
| } | } | ||||
| private void DeleteReport(ReportRepositoryItem item) { | |||||
| private async void DeleteReport(ReportRepositoryItem item) { | |||||
| try { | |||||
| await ReportRepositoryService.DeleteReport(item); | |||||
| pendingReports.Remove(item); | |||||
| StateHasChanged(); | |||||
| Toaster.ShowSuccess(i18n.GetString("Success.DeleteReport.Title"), i18n.GetString("Success.DeleteReport.Msg", item.ID)); | |||||
| } catch (Exception ex) { | |||||
| Toaster.ShowWarning(i18n.GetString("Error.DeleteReport.Title"), i18n.GetString("Error.DeleteReport.Msg", item.ID)); | |||||
| } | |||||
| } | } | ||||
| private void SendReport(ReportRepositoryItem item) { | private void SendReport(ReportRepositoryItem item) { |
| using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | ||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Net.Http; | using System.Net.Http; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using TG.Blazor.IndexedDB; | |||||
| namespace CaritasPWA { | namespace CaritasPWA { | ||||
| public class Program { | public class Program { | ||||
| builder.Services.AddMatBlazor(); | builder.Services.AddMatBlazor(); | ||||
| 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<IBicycleRestService, BicycleRestService>(); | |||||
| builder.Services.AddScoped<IBicycleRestService, BicycleRestService>(); | |||||
| builder.Services.AddSingleton<AppState>(); | builder.Services.AddSingleton<AppState>(); | ||||
| builder.Services.AddSingleton<PageHistoryManager>(); | builder.Services.AddSingleton<PageHistoryManager>(); | ||||
| builder.Services.AddSingleton<ReportDataProvider>(); | builder.Services.AddSingleton<ReportDataProvider>(); | ||||
| builder.Services.AddSingleton<OnlineStatusProvider>(); | builder.Services.AddSingleton<OnlineStatusProvider>(); | ||||
| builder.Services.AddSingleton<ReportRepositoryService>(); | |||||
| builder.Services.AddScoped<ReportRepositoryService>(); | |||||
| builder.Services.AddScoped<Toaster>(); | builder.Services.AddScoped<Toaster>(); | ||||
| builder.Services.AddScoped<UserDataProvider>(); | builder.Services.AddScoped<UserDataProvider>(); | ||||
| builder.Services.AddScoped<MasterDataService>(); | builder.Services.AddScoped<MasterDataService>(); | ||||
| config.HideTransitionDuration = 150; | config.HideTransitionDuration = 150; | ||||
| }); | }); | ||||
| builder.Services.AddIndexedDB(dbStore => { | |||||
| dbStore.DbName = "CwebPlusAppDB"; | |||||
| dbStore.Version = 1; | |||||
| dbStore.Stores.Add(new StoreSchema { | |||||
| Name = "FoundReportRepositoryItems", | |||||
| PrimaryKey = new IndexSpec { Name = "id", KeyPath = "id", Auto = true }, | |||||
| Indexes = new List<IndexSpec> { | |||||
| new IndexSpec{Name="serverRefNbr", KeyPath = "serverRefNbr", Auto=false}, | |||||
| new IndexSpec{Name="status", KeyPath = "status", Auto=false} | |||||
| } | |||||
| }); | |||||
| dbStore.Stores.Add(new StoreSchema { | |||||
| Name = "MissingReportRepositoryItems", | |||||
| PrimaryKey = new IndexSpec { Name = "id", KeyPath = "id", Auto = true }, | |||||
| Indexes = new List<IndexSpec> { | |||||
| new IndexSpec{Name="serverRefNbr", KeyPath = "serverRefNbr", Auto=false}, | |||||
| new IndexSpec{Name="status", KeyPath = "status", Auto=false} | |||||
| } | |||||
| }); | |||||
| }); | |||||
| await builder.Build().RunAsync(); | await builder.Build().RunAsync(); | ||||
| } | } |
| private FoundReport report; | private FoundReport report; | ||||
| public FoundReport Report { get => report; set => report = value; } | public FoundReport Report { get => report; set => report = value; } | ||||
| public FoundReportRepositoryItem() : base(Type.FOUND, null) { | |||||
| } | |||||
| public FoundReportRepositoryItem(FoundReport _report, long identifier) : base(Type.FOUND, identifier) { | public FoundReportRepositoryItem(FoundReport _report, long identifier) : base(Type.FOUND, identifier) { | ||||
| this.report = _report; | this.report = _report; | ||||
| } | } | ||||
| public override FoundReport GetReport() { | |||||
| return report; | |||||
| } | |||||
| } | } | ||||
| } | } |
| private MissingReport report; | private MissingReport report; | ||||
| public MissingReport Report { get => report; set => report = value; } | public MissingReport Report { get => report; set => report = value; } | ||||
| public MissingReportRepositoryItem() : base(Type.MISSING, null) { | |||||
| } | |||||
| public MissingReportRepositoryItem(MissingReport _report, long identifier) : base(Type.MISSING, identifier) { | public MissingReportRepositoryItem(MissingReport _report, long identifier) : base(Type.MISSING, identifier) { | ||||
| this.report = _report; | this.report = _report; | ||||
| } | } | ||||
| public override MissingReport GetReport() { | |||||
| return report; | |||||
| } | |||||
| } | } | ||||
| } | } |
| public abstract class ReportRepositoryItem { | public abstract class ReportRepositoryItem { | ||||
| public enum Type { FOUND, MISSING } | public enum Type { FOUND, MISSING } | ||||
| public enum State { PENDING, TRANSMITTED } | |||||
| private long id; | private long id; | ||||
| private string serverRefNbr; | private string serverRefNbr; | ||||
| private bool transmitted; | |||||
| private State status; | |||||
| private Type reportType; | private Type reportType; | ||||
| public long ID { get => id; set => id = value; } | public long ID { get => id; set => id = value; } | ||||
| public string ServerRefNbr { get => serverRefNbr; set => serverRefNbr = value; } | public string ServerRefNbr { get => serverRefNbr; set => serverRefNbr = value; } | ||||
| public bool Transmitted { get => transmitted; set => transmitted = value; } | |||||
| public State Status { get => status; set => status = value; } | |||||
| public Type ReportType { get => reportType; set => reportType = value; } | public Type ReportType { get => reportType; set => reportType = value; } | ||||
| public ReportRepositoryItem(Type _reportType, long identifier) { | |||||
| this.id = identifier; | |||||
| public ReportRepositoryItem(Type _reportType, long? identifier) { | |||||
| this.id = identifier.HasValue ? identifier.Value : 0; | |||||
| this.reportType = _reportType; | this.reportType = _reportType; | ||||
| this.transmitted = false; | |||||
| this.status = State.PENDING; | |||||
| } | } | ||||
| public override bool Equals(Object obj) { | public override bool Equals(Object obj) { | ||||
| public override string ToString() { | public override string ToString() { | ||||
| return base.ToString(); | return base.ToString(); | ||||
| } | } | ||||
| public abstract Report GetReport(); | |||||
| } | } | ||||
| } | } |
| <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.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>Die Meldung mit der ID {0:d} konnte nicht gelöscht werden!</value> | |||||
| </data> | |||||
| <data name="Error.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Löschung der Meldung fehlgeschlagen!</value> | |||||
| </data> | |||||
| <data name="Error.GeoLocation.Msg" xml:space="preserve"> | <data name="Error.GeoLocation.Msg" xml:space="preserve"> | ||||
| <value>Die Geoposition konnte nicht ermittelt werden. Fehlermeldung : {0:s}</value> | <value>Die Geoposition konnte nicht ermittelt werden. Fehlermeldung : {0:s}</value> | ||||
| </data> | </data> | ||||
| <data name="Specifications" xml:space="preserve"> | <data name="Specifications" xml:space="preserve"> | ||||
| <value>Angaben</value> | <value>Angaben</value> | ||||
| </data> | </data> | ||||
| <data name="Success.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>Die Meldung mit der ID {0:d} wurde erfolgreich gelöscht!</value> | |||||
| </data> | |||||
| <data name="Success.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Meldung gelöscht!</value> | |||||
| </data> | |||||
| <data name="Type" xml:space="preserve"> | <data name="Type" xml:space="preserve"> | ||||
| <value>Typ</value> | <value>Typ</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.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>Le rapport avec l'ID {0:d} n'a pas pu être supprimé !</value> | |||||
| </data> | |||||
| <data name="Error.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>La suppression du rapport a échoué !</value> | |||||
| </data> | |||||
| <data name="Error.GeoLocation.Msg" xml:space="preserve"> | <data name="Error.GeoLocation.Msg" xml:space="preserve"> | ||||
| <value>La géoposition n'a pas pu être déterminée. Message d'erreur : {0:s}</value> | <value>La géoposition n'a pas pu être déterminée. Message d'erreur : {0:s}</value> | ||||
| </data> | </data> | ||||
| <data name="Specifications" xml:space="preserve"> | <data name="Specifications" xml:space="preserve"> | ||||
| <value>Description détaillée</value> | <value>Description détaillée</value> | ||||
| </data> | </data> | ||||
| <data name="Success.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>Le rapport avec l'ID {0:d} a été supprimé avec succès!</value> | |||||
| </data> | |||||
| <data name="Success.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Rapport supprimé!</value> | |||||
| </data> | |||||
| <data name="Type" xml:space="preserve"> | <data name="Type" xml:space="preserve"> | ||||
| <value>Typ</value> | <value>Typ</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.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>Il rapporto con ID {0:d} non può essere cancellato!</value> | |||||
| </data> | |||||
| <data name="Error.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Cancellazione del rapporto fallita!</value> | |||||
| </data> | |||||
| <data name="Error.GeoLocation.Msg" xml:space="preserve"> | <data name="Error.GeoLocation.Msg" xml:space="preserve"> | ||||
| <value>Non è stato possibile determinare la posizione geografica. Messaggio d'errore: {0:s}</value> | <value>Non è stato possibile determinare la posizione geografica. Messaggio d'errore: {0:s}</value> | ||||
| </data> | </data> | ||||
| <data name="Specifications" xml:space="preserve"> | <data name="Specifications" xml:space="preserve"> | ||||
| <value>Descrizione dettagliata</value> | <value>Descrizione dettagliata</value> | ||||
| </data> | </data> | ||||
| <data name="Success.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>Il rapporto con l'ID {0:d} è stato cancellato con successo!</value> | |||||
| </data> | |||||
| <data name="Success.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Rapporto cancellato!</value> | |||||
| </data> | |||||
| <data name="Type" xml:space="preserve"> | <data name="Type" xml:space="preserve"> | ||||
| <value>Tipo</value> | <value>Tipo</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.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>The Report with ID {0:d} could not be deleted!</value> | |||||
| </data> | |||||
| <data name="Error.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Report deletion failed!</value> | |||||
| </data> | |||||
| <data name="Error.GeoLocation.Msg" xml:space="preserve"> | <data name="Error.GeoLocation.Msg" xml:space="preserve"> | ||||
| <value>The Geo Location couldn't be get. ErrorMessage : {0:s}</value> | <value>The Geo Location couldn't be get. ErrorMessage : {0:s}</value> | ||||
| </data> | </data> | ||||
| <data name="Specifications" xml:space="preserve"> | <data name="Specifications" xml:space="preserve"> | ||||
| <value>Specifications</value> | <value>Specifications</value> | ||||
| </data> | </data> | ||||
| <data name="Success.DeleteReport.Msg" xml:space="preserve"> | |||||
| <value>The Report with ID {0:d} was successfully deleted!</value> | |||||
| </data> | |||||
| <data name="Success.DeleteReport.Title" xml:space="preserve"> | |||||
| <value>Report deleted!</value> | |||||
| </data> | |||||
| <data name="Type" xml:space="preserve"> | <data name="Type" xml:space="preserve"> | ||||
| <value>Type</value> | <value>Type</value> | ||||
| </data> | </data> |
| public async Task<ReportResponse> SendFoundReport(Report report) { | public async Task<ReportResponse> SendFoundReport(Report report) { | ||||
| string subResourceUrl = configuration.GetValue<string>("subresource_url_foundreport"); | string subResourceUrl = configuration.GetValue<string>("subresource_url_foundreport"); | ||||
| return await SendReport(report, subResourceUrl, new FoundReportRepositoryItem((FoundReport)report, ReportRepositoryService.GetCurrentTimeInMillis())); | |||||
| return await SendReport(report, subResourceUrl, new FoundReportRepositoryItem((FoundReport)report, 0)); | |||||
| } | } | ||||
| public async Task<ReportResponse> SendFoundReport(FoundReportRepositoryItem reportRepositoryItem) { | public async Task<ReportResponse> SendFoundReport(FoundReportRepositoryItem reportRepositoryItem) { | ||||
| public async Task<ReportResponse> SendMissingReport(Report report) { | public async Task<ReportResponse> SendMissingReport(Report report) { | ||||
| string subResourceUrl = configuration.GetValue<string>("subresource_url_missingreport"); | string subResourceUrl = configuration.GetValue<string>("subresource_url_missingreport"); | ||||
| return await SendReport(report, subResourceUrl, new MissingReportRepositoryItem((MissingReport)report, ReportRepositoryService.GetCurrentTimeInMillis())); | |||||
| return await SendReport(report, subResourceUrl, new MissingReportRepositoryItem((MissingReport)report, 0)); | |||||
| } | } | ||||
| public async Task<ReportResponse> SendMissingReport(MissingReportRepositoryItem reportRepositoryItem) { | public async Task<ReportResponse> SendMissingReport(MissingReportRepositoryItem reportRepositoryItem) { | ||||
| protected async Task<ReportResponse> SendReport(Report report, string subResourceUrl, ReportRepositoryItem reportRepositoryItem) { | protected async Task<ReportResponse> SendReport(Report report, string subResourceUrl, ReportRepositoryItem reportRepositoryItem) { | ||||
| ReportResponse response = null; | ReportResponse response = null; | ||||
| if (onlineStatusProvider.Online && !reportRepositoryItem.Transmitted) { | |||||
| if (onlineStatusProvider.Online && ReportRepositoryItem.State.PENDING.Equals(reportRepositoryItem.Status)) { | |||||
| if (httpClient != null) { | if (httpClient != null) { | ||||
| if (!String.IsNullOrEmpty(subResourceUrl)) { | if (!String.IsNullOrEmpty(subResourceUrl)) { | ||||
| string reportJson = JsonConvert.SerializeObject(report); | string reportJson = JsonConvert.SerializeObject(report); | ||||
| response.StatusCode = httpResult.StatusCode; | response.StatusCode = httpResult.StatusCode; | ||||
| if (HttpStatusCode.OK == response.StatusCode) { | if (HttpStatusCode.OK == response.StatusCode) { | ||||
| reportRepositoryItem.ServerRefNbr = response.Data[0]; | reportRepositoryItem.ServerRefNbr = response.Data[0]; | ||||
| reportRepositoryItem.Transmitted = true; | |||||
| reportRepositoryItem.Status = ReportRepositoryItem.State.TRANSMITTED; | |||||
| await reportRepositoryService.SaveReport(reportRepositoryItem); | await reportRepositoryService.SaveReport(reportRepositoryItem); | ||||
| } | } | ||||
| return response; | return response; |
| using cwebplusApp.Shared.Models; | using cwebplusApp.Shared.Models; | ||||
| using Microsoft.JSInterop; | using Microsoft.JSInterop; | ||||
| using Newtonsoft.Json; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using TG.Blazor.IndexedDB; | |||||
| namespace cwebplusApp.Shared.Services { | namespace cwebplusApp.Shared.Services { | ||||
| public sealed class ReportRepositoryService { | public sealed class ReportRepositoryService { | ||||
| private const string KeyNameFoundReports = "foundReportRepository"; | |||||
| private const string KeyNameMissingReports = "missingReportRepository"; | |||||
| private const string FoundReportRepository_Store_Name = "FoundReportRepositoryItems"; | |||||
| private const string MissingReportRepository_Store_Name = "MissingReportRepositoryItems"; | |||||
| private readonly IJSRuntime jsRuntime; | private readonly IJSRuntime jsRuntime; | ||||
| private bool initialized; | private bool initialized; | ||||
| public event EventHandler Changed; | |||||
| private readonly IndexedDBManager dbManager; | |||||
| public ReportRepositoryService(IJSRuntime jsRuntime) { | |||||
| public ReportRepositoryService(IJSRuntime jsRuntime, IndexedDBManager _dbManager) { | |||||
| this.jsRuntime = jsRuntime; | this.jsRuntime = jsRuntime; | ||||
| this.dbManager = _dbManager; | |||||
| } | } | ||||
| public async Task SaveReport(ReportRepositoryItem reportRepositoryItem) { | public async Task SaveReport(ReportRepositoryItem reportRepositoryItem) { | ||||
| } | } | ||||
| public async ValueTask<List<FoundReportRepositoryItem>> GetFoundReports() { | public async ValueTask<List<FoundReportRepositoryItem>> GetFoundReports() { | ||||
| // 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 (!initialized) { | |||||
| // Create a reference to the current object, so the JS function can call the public method "OnStorageUpdated" | |||||
| var reference = DotNetObjectReference.Create(this); | |||||
| await this.jsRuntime.InvokeVoidAsync("BlazorRegisterStorageEvent", reference); | |||||
| this.initialized = true; | |||||
| } | |||||
| // Read the JSON string that contains the data from the local storage | |||||
| List<FoundReportRepositoryItem> result; | |||||
| var str = await this.jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameFoundReports); | |||||
| if (str != null) { | |||||
| result = JsonConvert.DeserializeObject<List<FoundReportRepositoryItem>>(str) ?? new(); | |||||
| } else { | |||||
| result = new(); | |||||
| } | |||||
| return result; | |||||
| return await this.dbManager.GetRecords<FoundReportRepositoryItem>(FoundReportRepository_Store_Name); | |||||
| } | } | ||||
| public async ValueTask<List<FoundReportRepositoryItem>> GetPendingFoundReports() { | public async ValueTask<List<FoundReportRepositoryItem>> GetPendingFoundReports() { | ||||
| List<FoundReportRepositoryItem> pendingFoundReps = new(); | |||||
| List<FoundReportRepositoryItem> foundReps = await GetFoundReports(); | |||||
| foreach (FoundReportRepositoryItem report in foundReps) { | |||||
| if (!report.Transmitted) { | |||||
| pendingFoundReps.Add(report); | |||||
| } | |||||
| } | |||||
| return pendingFoundReps; | |||||
| var indexSearch = new StoreIndexQuery<ReportRepositoryItem.State> { | |||||
| Storename = FoundReportRepository_Store_Name, | |||||
| IndexName = "status", | |||||
| QueryValue = ReportRepositoryItem.State.PENDING | |||||
| }; | |||||
| return new List<FoundReportRepositoryItem>(await this.dbManager.GetAllRecordsByIndex<ReportRepositoryItem.State, FoundReportRepositoryItem>(indexSearch)); | |||||
| } | } | ||||
| public async ValueTask<List<MissingReportRepositoryItem>> GetMissingReports() { | |||||
| // 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 (!initialized) { | |||||
| // Create a reference to the current object, so the JS function can call the public method "OnStorageUpdated" | |||||
| var reference = DotNetObjectReference.Create(this); | |||||
| await this.jsRuntime.InvokeVoidAsync("BlazorRegisterStorageEvent", reference); | |||||
| this.initialized = true; | |||||
| } | |||||
| // Read the JSON string that contains the data from the local storage | |||||
| List<MissingReportRepositoryItem> result; | |||||
| var str = await this.jsRuntime.InvokeAsync<string>("BlazorGetLocalStorage", KeyNameMissingReports); | |||||
| if (str != null) { | |||||
| result = JsonConvert.DeserializeObject<List<MissingReportRepositoryItem>>(str) ?? new(); | |||||
| } else { | |||||
| result = new(); | |||||
| } | |||||
| return result; | |||||
| public async ValueTask<List<FoundReportRepositoryItem>> GetTransmittedFoundReports() { | |||||
| var indexSearch = new StoreIndexQuery<ReportRepositoryItem.State> { | |||||
| Storename = FoundReportRepository_Store_Name, | |||||
| IndexName = "status", | |||||
| QueryValue = ReportRepositoryItem.State.TRANSMITTED | |||||
| }; | |||||
| return new List<FoundReportRepositoryItem>(await this.dbManager.GetAllRecordsByIndex<ReportRepositoryItem.State, FoundReportRepositoryItem>(indexSearch)); | |||||
| } | } | ||||
| public async ValueTask<List<MissingReportRepositoryItem>> GetPendingMissingReports() { | |||||
| List<MissingReportRepositoryItem> pendingMissingReps = new(); | |||||
| List<MissingReportRepositoryItem> missingReps = await GetMissingReports(); | |||||
| foreach (MissingReportRepositoryItem report in missingReps) { | |||||
| if (!report.Transmitted) { | |||||
| pendingMissingReps.Add(report); | |||||
| } | |||||
| } | |||||
| return pendingMissingReps; | |||||
| public async ValueTask<List<MissingReportRepositoryItem>> GetMissingReports() { | |||||
| return await this.dbManager.GetRecords<MissingReportRepositoryItem>(MissingReportRepository_Store_Name); | |||||
| } | } | ||||
| public async Task SaveFoundReport(FoundReportRepositoryItem foundReportRepositoryItem) { | |||||
| List<FoundReportRepositoryItem> foundReps = await GetFoundReports(); | |||||
| foundReps.Remove(foundReportRepositoryItem); | |||||
| foundReps.Add(foundReportRepositoryItem); | |||||
| var json = JsonConvert.SerializeObject(foundReps); | |||||
| await jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameFoundReports, json); | |||||
| public async ValueTask<List<MissingReportRepositoryItem>> GetPendingMissingReports() { | |||||
| var indexSearch = new StoreIndexQuery<ReportRepositoryItem.State> { | |||||
| Storename = MissingReportRepository_Store_Name, | |||||
| IndexName = "status", | |||||
| QueryValue = ReportRepositoryItem.State.PENDING | |||||
| }; | |||||
| return new List<MissingReportRepositoryItem>(await this.dbManager.GetAllRecordsByIndex<ReportRepositoryItem.State, MissingReportRepositoryItem>(indexSearch)); | |||||
| } | } | ||||
| public async Task SaveMissingReport(MissingReportRepositoryItem missingReportRepositoryItem) { | |||||
| List<MissingReportRepositoryItem> missingReps = await GetMissingReports(); | |||||
| missingReps.Remove(missingReportRepositoryItem); | |||||
| missingReps.Add(missingReportRepositoryItem); | |||||
| var json = JsonConvert.SerializeObject(missingReps); | |||||
| await jsRuntime.InvokeVoidAsync("BlazorSetLocalStorage", KeyNameMissingReports, json); | |||||
| public async ValueTask<List<MissingReportRepositoryItem>> GetTransmittedMissingReports() { | |||||
| var indexSearch = new StoreIndexQuery<ReportRepositoryItem.State> { | |||||
| Storename = MissingReportRepository_Store_Name, | |||||
| IndexName = "status", | |||||
| QueryValue = ReportRepositoryItem.State.TRANSMITTED | |||||
| }; | |||||
| return new List<MissingReportRepositoryItem>(await this.dbManager.GetAllRecordsByIndex<ReportRepositoryItem.State, MissingReportRepositoryItem>(indexSearch)); | |||||
| } | } | ||||
| public async ValueTask<int> GetNbrOfPendingReports() { | public async ValueTask<int> GetNbrOfPendingReports() { | ||||
| List<FoundReportRepositoryItem> foundReportRepositoryItems = await GetPendingFoundReports(); | |||||
| IList<FoundReportRepositoryItem> foundReportRepositoryItems = await GetPendingFoundReports(); | |||||
| List<MissingReportRepositoryItem> missingReportRepositoryItems = await GetPendingMissingReports(); | List<MissingReportRepositoryItem> missingReportRepositoryItems = await GetPendingMissingReports(); | ||||
| return foundReportRepositoryItems.Count + missingReportRepositoryItems.Count; | return foundReportRepositoryItems.Count + missingReportRepositoryItems.Count; | ||||
| } | } | ||||
| // This method is called from BlazorRegisterStorageEvent when the storage changed | |||||
| [JSInvokable] | |||||
| public void OnStorageUpdated(string key) { | |||||
| if (key == KeyNameMissingReports || key == KeyNameFoundReports) { | |||||
| // Reset the settings. The next call to Get will reload the data | |||||
| Changed?.Invoke(this, EventArgs.Empty); | |||||
| public async Task SaveFoundReport(FoundReportRepositoryItem foundReportRepositoryItem) { | |||||
| var newRecord = new StoreRecord<FoundReportRepositoryItem> { | |||||
| Storename = FoundReportRepository_Store_Name, | |||||
| Data = foundReportRepositoryItem | |||||
| }; | |||||
| if (foundReportRepositoryItem.ID == 0) { | |||||
| foundReportRepositoryItem.ID = GetCurrentTimeInMillis(); | |||||
| await this.dbManager.AddRecord(newRecord); | |||||
| } else { | |||||
| await this.dbManager.UpdateRecord(newRecord); | |||||
| } | |||||
| } | |||||
| public async Task SaveMissingReport(MissingReportRepositoryItem missingReportRepositoryItem) { | |||||
| var newRecord = new StoreRecord<MissingReportRepositoryItem> { | |||||
| Storename = MissingReportRepository_Store_Name, | |||||
| Data = missingReportRepositoryItem | |||||
| }; | |||||
| if (missingReportRepositoryItem.ID == 0) { | |||||
| missingReportRepositoryItem.ID = GetCurrentTimeInMillis(); | |||||
| await this.dbManager.AddRecord(newRecord); | |||||
| } else { | |||||
| await this.dbManager.UpdateRecord(newRecord); | |||||
| } | |||||
| } | |||||
| public async Task DeleteReport(ReportRepositoryItem reportRepositoryItem) { | |||||
| if (reportRepositoryItem is FoundReportRepositoryItem) { | |||||
| await this.dbManager.DeleteRecord(FoundReportRepository_Store_Name, reportRepositoryItem.ID); | |||||
| } else { | |||||
| await this.dbManager.DeleteRecord(MissingReportRepository_Store_Name, reportRepositoryItem.ID); | |||||
| } | } | ||||
| } | } | ||||
| @using Microsoft.AspNetCore.Components.Routing | @using Microsoft.AspNetCore.Components.Routing | ||||
| @using Microsoft.AspNetCore.Components.Web | @using Microsoft.AspNetCore.Components.Web | ||||
| @using Microsoft.AspNetCore.Components.WebAssembly.Http | @using Microsoft.AspNetCore.Components.WebAssembly.Http | ||||
| @using Microsoft.AspNetCore.Components.WebAssembly.Services | |||||
| @using Microsoft.Extensions.Localization | @using Microsoft.Extensions.Localization | ||||
| @using Microsoft.JSInterop | @using Microsoft.JSInterop | ||||
| @using MatBlazor | @using MatBlazor | ||||
| @using BlazorAnimate | @using BlazorAnimate | ||||
| @using FisSst.BlazorMaps | @using FisSst.BlazorMaps | ||||
| @using BlazorGeolocation | @using BlazorGeolocation | ||||
| @using TG.Blazor.IndexedDB | |||||
| @using CaritasPWA | @using CaritasPWA | ||||
| @using cwebplusApp.Shared | @using cwebplusApp.Shared | ||||
| @using cwebplusApp.Shared.ResourceFiles | @using cwebplusApp.Shared.ResourceFiles |
| <PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.9" /> | <PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.9" /> | ||||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | ||||
| <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" /> | <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" /> | ||||
| <PackageReference Include="TG.Blazor.IndexedDB" Version="1.5.0-preview" /> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> |
| <a class="dismiss">🗙</a> | <a class="dismiss">🗙</a> | ||||
| </div> | </div> | ||||
| <script src="_framework/blazor.webassembly.js"></script> | <script src="_framework/blazor.webassembly.js"></script> | ||||
| <script src="_content/TG.Blazor.IndexedDB/indexedDb.Blazor.js"></script> | |||||
| <script> | <script> | ||||
| if ('serviceWorker' in navigator) { | if ('serviceWorker' in navigator) { | ||||
| navigator.serviceWorker.register('service-worker.js') | navigator.serviceWorker.register('service-worker.js') |
| '_content/matblazor/dist/matblazor.js', | '_content/matblazor/dist/matblazor.js', | ||||
| '_content/blazoranimate/blazoranimateinterop.js', | '_content/blazoranimate/blazoranimateinterop.js', | ||||
| '_content/blazoranimate/aos.css', | '_content/blazoranimate/aos.css', | ||||
| '_content/TG.Blazor.IndexedDB/indexedDb.Blazor.js', | |||||
| '_framework/blazor.webassembly.js', | '_framework/blazor.webassembly.js', | ||||
| '_framework/blazor.boot.json', | '_framework/blazor.boot.json', | ||||
| '_framework/dotnet.5.0.9.js', | '_framework/dotnet.5.0.9.js', | ||||
| // fetch events (Network first strategy, no cache update after install) | // fetch events (Network first strategy, no cache update after install) | ||||
| self.addEventListener('fetch', function (event) { | self.addEventListener('fetch', function (event) { | ||||
| event.respondWith(fromNetwork(event.request, 6000).catch(function () { | |||||
| event.respondWith(fromNetwork(event.request, 15000).catch(function () { | |||||
| return fromCache(event.request); | return fromCache(event.request); | ||||
| })); | })); | ||||
| }); | }); |