Procházet zdrojové kódy

Offline mode

master
Flo Smilari před 4 roky
rodič
revize
d5f3e67021

+ 27
- 6
Pages/AccountPage.razor Zobrazit soubor

@@ -54,11 +54,23 @@
</div>
</div>
@if (string.IsNullOrEmpty(FromRoute)) {
<div class="row no-gutters align-items-end justify-content-center w-100" style="padding-bottom:2em">
<MatButton Class="w-100" Raised="true" @onclick="SaveUserData">@i18n["Save"]</MatButton>
@if (!string.IsNullOrEmpty(FromRoute)) {
<div class="row no-gutters justify-content-end w-100">
<MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default" @onclick="SaveUserData" Style="background: lightgrey; width: 64px; height: 64px; border-radius: 32px; align-items: flex-end; justify-content: center; display: inline-flex;">
<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="M8,8.5c0.83,0,1.5-0.67,1.5-1.5S8.83,5.5,8,5.5S6.5,6.17,6.5,7S7.17,8.5,8,8.5z M12.28,13.66 C10.98,12.9,9.5,12.5,8,12.5s-2.98,0.4-4.28,1.16c-0.14,0.08-0.22,0.25-0.22,0.42v0.41h9v-0.41 C12.5,13.91,12.41,13.74,12.28,13.66z" opacity=".3" />
<path d="M8,10c1.66,0,3-1.34,3-3S9.66,4,8,4S5,5.34,5,7S6.34,10,8,10z M8,5.5c0.83,0,1.5,0.67,1.5,1.5S8.83,8.5,8,8.5 S6.5,7.83,6.5,7S7.17,5.5,8,5.5z M13.03,12.37C11.56,11.5,9.84,11,8,11s-3.56,0.5-5.03,1.37C2.36,12.72,2,13.39,2,14.09V16h12 v-1.91C14,13.39,13.64,12.72,13.03,12.37z M12.5,14.5h-9v-0.41c0-0.18,0.09-0.34,0.22-0.42C5.02,12.9,6.5,12.5,8,12.5 s2.98,0.4,4.28,1.16c0.14,0.08,0.22,0.25,0.22,0.42V14.5z" />
</g>
<polygon points="18,7.75 16.25,7.75 16.25,6 14.75,6 14.75,7.75 13,7.75 13,9.25 14.75,9.25 14.75,11 16.25,11 16.25,9.25 18,9.25" />
</g>
</svg>
</label>
</MatRipple>
</div>
} else {
<div class="row no-gutters align-items-end justify-content-center w-100" style="padding-bottom:2em">
<div class="col" style="padding-right:0.5em">
<MatButton Class="w-100" Outlined="true" @onclick="Cancel">@i18n["Cancel"]</MatButton>
@@ -67,6 +79,10 @@
<MatButton Class="w-100" Raised="true" @onclick="Next">@i18n["Send"]</MatButton>
</div>
</div>
} else {
<div class="row no-gutters align-items-end justify-content-center w-100" style="padding-bottom:2em">
<MatButton Class="w-100" Raised="true" @onclick="SaveUserDataAndClose">@i18n["Save"]</MatButton>
</div>
}
</div>
@@ -83,7 +99,7 @@
PageHistoryManager.OnBeforeNavigateBack = new EventCallback(this, (Action)OnBeforeNavigateBack);
PageHistoryManager.AddPageToHistory(NavigationManager.Uri);
Account = await GetUserData();
if (ReportDataProvider.Report != null) {
if (!string.IsNullOrEmpty(FromRoute) && ReportDataProvider.Report != null) {
UserDataProvider.mapUserData(Account, ReportDataProvider.Report);
}
StateHasChanged();
@@ -95,11 +111,16 @@
}
}
private async void SaveUserData() {
private async Task SaveUserData() {
await UserDataProvider.Save(Account);
}
private async void SaveUserDataAndClose() {
await SaveUserData();
NavigationManager.NavigateTo("caritas_services");
}
private async Task<UserData> GetUserData() {
return await UserDataProvider.Get();
}

+ 1
- 0
Pages/CaritasServiceFundVeloFoundConclusion.razor Zobrazit soubor

@@ -92,6 +92,7 @@
Toaster.ShowError(response.Message, response.GetDataAsFormattedList());
} else {
Toaster.ShowWarning(i18n.GetString("Warning.NoConnection.Title"), i18n.GetString("Warning.NoConnection.Msg"));
PageHistoryManager.Reset();
}
StateHasChanged();
AppState.NotifyChanged();

+ 1
- 0
Pages/CaritasServiceFundVeloLostFoundPage.razor Zobrazit soubor

@@ -45,6 +45,7 @@
protected override void OnInitialized() {
PageHistoryManager.AddPageToHistory(NavigationManager.Uri);
ReportDataProvider.Report = null;
ReportDataProvider.ReportRepositoryItem = null;
base.OnInitialized();
}

+ 15
- 6
Pages/CaritasServiceFundVeloMissingConclusion.razor Zobrazit soubor

@@ -25,7 +25,7 @@
<h6 style="font-style:italic;padding-bottom:1em">@i18n["Info.Report.Transmitting"]</h6>
</div>
} else {
if (responseOk) {
if (ResposeStatus.OK == responseStatus) {
<MatHeadline5 Style="font-family:Ubuntu; text-align:center">@i18n["FinishedTextMissing"]</MatHeadline5>
<MatSubtitle1 Class="w-100" Style="font-family:Ubuntu; text-align:left; font-weight:800">@i18n["FinishedTextMissing_Heading1"]</MatSubtitle1>
<ul class="w-100">
@@ -87,7 +87,13 @@
@code {
private bool responseOk = false;
enum ResposeStatus : ushort {
OK = 1,
Error = 10,
NoConnection = 20
}
private ResposeStatus responseStatus = ResposeStatus.NoConnection;
private bool running = true;
ReportResponse response;
@@ -96,18 +102,21 @@
PageHistoryManager.AddPageToHistory(NavigationManager.Uri);
try {
response = await IBicycleRestService.SendMissingReport(ReportDataProvider.Report);
responseOk = System.Net.HttpStatusCode.OK == response.StatusCode ? true : false;
responseStatus = response == null ? ResposeStatus.NoConnection : System.Net.HttpStatusCode.OK == response.StatusCode ? ResposeStatus.OK : ResposeStatus.Error;
} catch (HttpRequestException ex) {
response = new(i18n.GetString("MissingBike"), new string[] { ex.Message });
responseOk = false;
responseStatus = ResposeStatus.Error;
}
running = false;
if (responseOk) {
if (ResposeStatus.OK == responseStatus) {
Toaster.ShowSuccess(i18n.GetString("MissingBike"), response.Message);
PageHistoryManager.Reset();
} else {
} else if (ResposeStatus.Error == responseStatus) {
Toaster.ShowError(response.Message, response.GetDataAsFormattedList());
} else {
Toaster.ShowWarning(i18n.GetString("Warning.NoConnection.Title"), i18n.GetString("Warning.NoConnection.Msg"));
PageHistoryManager.Reset();
}
StateHasChanged();
AppState.NotifyChanged();

+ 3
- 6
Pages/IndexPage.razor Zobrazit soubor

@@ -10,8 +10,7 @@
@inject MasterDataService MasterDataService;
@inject Toaster Toaster;
@inject IConfiguration Configuration;
@inject IBicycleRestService IBicycleRestService;
@inject OnlineStatusProvider OnlineStatusProvider;
@inject IBicycleRestService BicycleRestService;
<div class="row h-100 justify-content-center">
@@ -22,9 +21,6 @@
<div class="row align-items-end vw-100 h-50">
<div class="col text-center">
<h3 style="font-style:italic;padding-bottom:1em">@i18n["Welcome"]</h3>
@*<div>
<MatButton Disabled="@btnDisabled" Raised="true" Style="width:50%" @onclick="@((e) => NavigateToNext())">@i18n["Login"]</MatButton>
</div>*@
</div>
</div>
<div class="row align-items-center justify-content-center vw-100 h-25">
@@ -52,8 +48,9 @@
showProgressCircle = true;
StateHasChanged();
try {
IBicycleRestService.Initialize(Configuration, OnlineStatusProvider);
BicycleRestService.Initialize(Configuration);
await MasterDataService.SynchronizeMasterdata();
await BicycleRestService.TrySendPendingReports();
} catch (Exception) {
Toaster.ShowWarning(i18n.GetString("Warning.Masterdata.Title"), i18n.GetString("Warning.Masterdata.Msg"));
} finally {

+ 1
- 0
Program.cs Zobrazit soubor

@@ -23,6 +23,7 @@ namespace CaritasPWA {
builder.Services.AddSingleton<PageHistoryManager>();
builder.Services.AddSingleton<ReportDataProvider>();
builder.Services.AddSingleton<OnlineStatusProvider>();
builder.Services.AddSingleton<ReportRepositoryService>();
builder.Services.AddScoped<Toaster>();
builder.Services.AddScoped<UserDataProvider>();
builder.Services.AddScoped<MasterDataService>();

+ 11
- 0
Shared/Models/FoundReportRepositoryItem.cs Zobrazit soubor

@@ -0,0 +1,11 @@
namespace cwebplusApp.Shared.Models {
public class FoundReportRepositoryItem : ReportRepositoryItem {
private FoundReport report;
public FoundReport Report { get => report; set => report = value; }
public FoundReportRepositoryItem(FoundReport _report, long identifier) : base(Type.FOUND, identifier) {
this.report = _report;
}
}
}

+ 11
- 0
Shared/Models/MissingReportRepositoryItem.cs Zobrazit soubor

@@ -0,0 +1,11 @@
namespace cwebplusApp.Shared.Models {
public class MissingReportRepositoryItem : ReportRepositoryItem {
private MissingReport report;
public MissingReport Report { get => report; set => report = value; }
public MissingReportRepositoryItem(MissingReport _report, long identifier) : base(Type.MISSING, identifier) {
this.report = _report;
}
}
}

+ 33
- 0
Shared/Models/ReportRepositoryItem.cs Zobrazit soubor

@@ -0,0 +1,33 @@
using System;
namespace cwebplusApp.Shared.Models {
public abstract class ReportRepositoryItem {
public enum Type { FOUND, MISSING }
private long id;
private string serverRefNbr;
private bool transmitted;
private Type reportType;
public long ID { get => id; set => id = value; }
public string ServerRefNbr { get => serverRefNbr; set => serverRefNbr = value; }
public bool Transmitted { get => transmitted; set => transmitted = value; }
public Type ReportType { get => reportType; set => reportType = value; }
public ReportRepositoryItem(Type _reportType, long identifier) {
this.id = identifier;
this.reportType = _reportType;
this.transmitted = false;
}
public override bool Equals(Object obj) {
if ((obj == null) || !this.GetType().Equals(obj.GetType())) {
return false;
} else {
ReportRepositoryItem rri = (ReportRepositoryItem)obj;
return (ID == rri.ID);
}
}
}
}

+ 21
- 13
Shared/NavMenu.razor Zobrazit soubor

@@ -119,21 +119,23 @@
private void LocationChanged(object sender, LocationChangedEventArgs e) {
locUrl = i18n.GetString(e.Location.Replace(NavigationManager.BaseUri, ""));
if (IsInServicesUrl(e)) {
if (IsInServicesUrl(e.Location)) {
Index = 1;
} else if (e.Location.Contains("account")) {
Index = 2;
} else if (e.Location.Contains("extras")) {
Index = 3;
} else if (e.Location.Contains("info")) {
Index = 4;
} else {
Index = 3;
Index = 0;
}
StateHasChanged();
}
private bool IsInServicesUrl(LocationChangedEventArgs e) {
return (e.Location.Contains("caritas_services") || e.Location.Contains("lost_found") || e.Location.Contains("keydata")
|| e.Location.Contains("account/") || e.Location.Contains("conclusion_"));
private bool IsInServicesUrl(string location) {
return (location.Contains("caritas_services") || location.Contains("lost_found") || location.Contains("keydata")
|| location.Contains("account/") || location.Contains("conclusion_"));
}
private bool HandleAppBarContainer() {
@@ -141,16 +143,22 @@
string baseUri = NavigationManager.BaseUri;
string delta = uri.Replace(baseUri, "");
if (delta.Equals("caritas_services")) {
Index = 1;
} else if (delta.Equals("account")) {
Index = 2;
} else if (delta.Equals("info")) {
Index = 4;
if (delta == null || delta.Equals("")) {
return false;
} else {
Index = 3;
if (IsInServicesUrl(delta)) {
Index = 1;
} else if (delta.Equals("account")) {
Index = 2;
} else if (delta.Equals("extras")) {
Index = 3;
} else if (delta.Equals("info")) {
Index = 4;
} else {
Index = 0;
}
return true;
}
return true;
}
private bool BackButtonDisabled() {

+ 75
- 19
Shared/Services/BicycleRestService.cs Zobrazit soubor

@@ -4,6 +4,7 @@ using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
@@ -16,13 +17,22 @@ namespace cwebplusApp.Shared.Services {
private static readonly string VERSION = "v1";
private HttpClient httpClient;
public IConfiguration Configuration { get; set; }
public OnlineStatusProvider OnlineStatusProvider { get; set; }
private IConfiguration configuration;
private OnlineStatusProvider onlineStatusProvider;
private ReportRepositoryService reportRepositoryService;
private ReportDataProvider reportDataProvider;
public void Initialize(IConfiguration configuration, OnlineStatusProvider onlineStatusProvider) {
this.Configuration = configuration;
this.OnlineStatusProvider = onlineStatusProvider;
string hostBaseUrl = Configuration.GetValue<string>("host_base_url");
public BicycleRestService(ReportRepositoryService _reportRepositoryService, OnlineStatusProvider _onlineStatusProvider,
ReportDataProvider _reportDataProvider) {
this.reportRepositoryService = _reportRepositoryService;
this.onlineStatusProvider = _onlineStatusProvider;
this.reportDataProvider = _reportDataProvider;
}
public void Initialize(IConfiguration _configuration) {
this.configuration = _configuration;
string hostBaseUrl = configuration.GetValue<string>("host_base_url");
if (!String.IsNullOrEmpty(hostBaseUrl)) {
this.httpClient = new HttpClient { BaseAddress = new Uri(hostBaseUrl) };
}
@@ -30,7 +40,7 @@ namespace cwebplusApp.Shared.Services {
public async Task<List<ColorItem>> GetColors() {
if (httpClient != null) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_colors");
string subResourceUrl = configuration.GetValue<string>("subresource_url_colors");
if (!String.IsNullOrEmpty(subResourceUrl)) {
HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));
@@ -46,7 +56,7 @@ namespace cwebplusApp.Shared.Services {
public async Task<List<BicycleType>> GetBicycleTypes() {
if (httpClient != null) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_types");
string subResourceUrl = configuration.GetValue<string>("subresource_url_types");
if (!String.IsNullOrEmpty(subResourceUrl)) {
HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));
@@ -62,7 +72,7 @@ namespace cwebplusApp.Shared.Services {
public async Task<List<Brand>> GetBrands() {
if (httpClient != null) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_brands");
string subResourceUrl = configuration.GetValue<string>("subresource_url_brands");
if (!String.IsNullOrEmpty(subResourceUrl)) {
HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));
@@ -77,33 +87,79 @@ namespace cwebplusApp.Shared.Services {
}
public async Task<ReportResponse> SendFoundReport(Report report) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_foundreport");
return await SendReport(report, subResourceUrl);
string subResourceUrl = configuration.GetValue<string>("subresource_url_foundreport");
return await SendReport(report, subResourceUrl, new FoundReportRepositoryItem((FoundReport)report, GetCurrentTimeInMillis()));
}
private async Task<ReportResponse> SendFoundReport(FoundReportRepositoryItem reportRepositoryItem) {
string subResourceUrl = configuration.GetValue<string>("subresource_url_foundreport");
return await SendReport(reportRepositoryItem.Report, subResourceUrl, reportRepositoryItem);
}
public async Task<ReportResponse> SendMissingReport(Report report) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_missingreport");
return await SendReport(report, subResourceUrl);
string subResourceUrl = configuration.GetValue<string>("subresource_url_missingreport");
return await SendReport(report, subResourceUrl, new MissingReportRepositoryItem((MissingReport)report, GetCurrentTimeInMillis()));
}
protected async Task<ReportResponse> SendReport(Report report, string subResourceUrl) {
if (OnlineStatusProvider.Online) {
public async Task<ReportResponse> SendMissingReport(MissingReportRepositoryItem reportRepositoryItem) {
string subResourceUrl = configuration.GetValue<string>("subresource_url_missingreport");
return await SendReport(reportRepositoryItem.Report, subResourceUrl, reportRepositoryItem);
}
public async Task TrySendPendingReports() {
await TrySendFoundPendingReports();
await TrySendMissingPendingReports();
}
public async Task TrySendFoundPendingReports() {
List<FoundReportRepositoryItem> pendingFoundReports = await reportRepositoryService.GetPendingFoundReports();
foreach (FoundReportRepositoryItem item in pendingFoundReports) {
try {
ReportResponse response = await SendFoundReport(item);
} catch (Exception) {
continue;
}
}
}
public async Task TrySendMissingPendingReports() {
List<MissingReportRepositoryItem> pendingMissingReports = await reportRepositoryService.GetPendingMissingReports();
foreach (MissingReportRepositoryItem item in pendingMissingReports) {
try {
ReportResponse response = await SendMissingReport(item);
} catch (Exception) {
continue;
}
}
}
protected async Task<ReportResponse> SendReport(Report report, string subResourceUrl, ReportRepositoryItem reportRepositoryItem) {
ReportResponse response = null;
if (onlineStatusProvider.Online && !reportRepositoryItem.Transmitted) {
if (httpClient != null) {
if (!String.IsNullOrEmpty(subResourceUrl)) {
string reportJson = JsonConvert.SerializeObject(report);
HttpContent content = new StringContent(reportJson, Encoding.UTF8, "application/json");
HttpResponseMessage httpResult = await httpClient.PostAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName), content);
string msg = await httpResult.Content.ReadAsStringAsync();
ReportResponse response = JsonConvert.DeserializeObject<ReportResponse>(msg);
response = JsonConvert.DeserializeObject<ReportResponse>(msg);
response.StatusCode = httpResult.StatusCode;
if (HttpStatusCode.OK == response.StatusCode) {
reportRepositoryItem.ServerRefNbr = response.Data[0];
reportRepositoryItem.Transmitted = true;
await reportRepositoryService.SaveReport(reportRepositoryItem);
}
return response;
}
}
throw new HttpRequestException("HTTP client not initialized!");
} else {
//TODO: Save to app storage
return null;
}
await reportRepositoryService.SaveReport(reportRepositoryItem);
return response;
}
private long GetCurrentTimeInMillis() {
return DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
}
}
}

+ 7
- 1
Shared/Services/IBicycleRestService.cs Zobrazit soubor

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace cwebplusApp.Shared.Services {
public interface IBicycleRestService {
void Initialize(IConfiguration configuration, OnlineStatusProvider onlineStatusProvider);
void Initialize(IConfiguration configuration);
Task<List<ColorItem>> GetColors();
@@ -17,5 +17,11 @@ namespace cwebplusApp.Shared.Services {
Task<ReportResponse> SendFoundReport(Report report);
Task<ReportResponse> SendMissingReport(Report report);
Task TrySendPendingReports();
Task TrySendFoundPendingReports();
Task TrySendMissingPendingReports();
}
}

+ 0
- 21
Shared/Services/ILFBicycleRest.cs Zobrazit soubor

@@ -1,21 +0,0 @@
using cwebplusApp.Shared.Models;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace cwebplusApp.Shared.Services {
public interface ILFBicycleRest {
void Initialize(IConfiguration configuration);
Task<List<ColorItem>> GetColors();
Task<List<BicycleType>> GetBicycleTypes();
Task<List<Brand>> GetBrands();
Task<ReportResponse> SendFoundReport(Report report);
Task<ReportResponse> SendMissingReport(Report report);
}
}

+ 0
- 104
Shared/Services/LFBicycleRest.cs Zobrazit soubor

@@ -1,104 +0,0 @@
using cwebplusApp.Shared.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace cwebplusApp.Shared.Services {
// REST interface responsible to submit lost or found reports and get the available master data.
public class LFBicycleRest : ILFBicycleRest {
private static readonly string VERSION = "v1";
private HttpClient httpClient;
[Inject]
public IConfiguration Configuration { get; set; }
public void Initialize(IConfiguration configuration) {
this.Configuration = configuration;
string hostBaseUrl = Configuration.GetValue<string>("host_base_url");
if (!String.IsNullOrEmpty(hostBaseUrl)) {
this.httpClient = new HttpClient { BaseAddress = new Uri(hostBaseUrl) };
}
}
public async Task<List<ColorItem>> GetColors() {
if (httpClient != null) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_colors");
if (!String.IsNullOrEmpty(subResourceUrl)) {
HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));
if (httpResult.StatusCode == System.Net.HttpStatusCode.OK) {
ColorItem[] colors = JsonConvert.DeserializeObject<ColorItem[]>(await httpResult.Content.ReadAsStringAsync());
return new List<ColorItem>(colors);
}
throw new HttpRequestException("HTTP error " + httpResult.StatusCode);
}
}
throw new HttpRequestException("HTTP client not initialized!");
}
public async Task<List<BicycleType>> GetBicycleTypes() {
if (httpClient != null) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_types");
if (!String.IsNullOrEmpty(subResourceUrl)) {
HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));
if (httpResult.StatusCode == System.Net.HttpStatusCode.OK) {
BicycleType[] bicycleTypes = JsonConvert.DeserializeObject<BicycleType[]>(await httpResult.Content.ReadAsStringAsync());
return new List<BicycleType>(bicycleTypes);
}
throw new HttpRequestException("HTTP error " + httpResult.StatusCode);
}
}
throw new HttpRequestException("HTTP client not initialized!");
}
public async Task<List<Brand>> GetBrands() {
if (httpClient != null) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_brands");
if (!String.IsNullOrEmpty(subResourceUrl)) {
HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName));
if (httpResult.StatusCode == System.Net.HttpStatusCode.OK) {
Brand[] brands = JsonConvert.DeserializeObject<Brand[]>(await httpResult.Content.ReadAsStringAsync());
return new List<Brand>(brands);
}
throw new HttpRequestException("HTTP error " + httpResult.StatusCode);
}
}
throw new HttpRequestException("HTTP client not initialized!");
}
public async Task<ReportResponse> SendFoundReport(Report report) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_foundreport");
return await SendReport(report, subResourceUrl);
}
public async Task<ReportResponse> SendMissingReport(Report report) {
string subResourceUrl = Configuration.GetValue<string>("subresource_url_missingreport");
return await SendReport(report, subResourceUrl);
}
protected async Task<ReportResponse> SendReport(Report report, string subResourceUrl) {
if (httpClient != null) {
if (!String.IsNullOrEmpty(subResourceUrl)) {
string reportJson = JsonConvert.SerializeObject(report);
HttpContent content = new StringContent(reportJson, Encoding.UTF8, "application/json");
HttpResponseMessage httpResult = await httpClient.PostAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName), content);
string msg = await httpResult.Content.ReadAsStringAsync();
ReportResponse response = JsonConvert.DeserializeObject<ReportResponse>(msg);
response.StatusCode = httpResult.StatusCode;
return response;
}
}
throw new HttpRequestException("HTTP client not initialized!");
}
}
}

+ 3
- 0
Shared/Services/MasterDataService.cs Zobrazit soubor

@@ -127,6 +127,9 @@ namespace cwebplusApp.Shared.Services {
} else if (key == KeyNameBcTypes) {
_bicycleTypes = null;
Changed?.Invoke(this, EventArgs.Empty);
} else if (key == KeyNameBrands) {
_brands = null;
Changed?.Invoke(this, EventArgs.Empty);
}
}

+ 1
- 0
Shared/Services/ReportDataProvider.cs Zobrazit soubor

@@ -4,6 +4,7 @@ namespace cwebplusApp.Shared.Services {
public class ReportDataProvider {
public Report Report { get; set; }
public ReportRepositoryItem ReportRepositoryItem { get; set; }
public FoundReport GetFoundReport() {

+ 119
- 0
Shared/Services/ReportRepositoryService.cs Zobrazit soubor

@@ -0,0 +1,119 @@
using cwebplusApp.Shared.Models;
using Microsoft.JSInterop;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace cwebplusApp.Shared.Services {
public sealed class ReportRepositoryService {
private const string KeyNameFoundReports = "foundReportRepository";
private const string KeyNameMissingReports = "missingReportRepository";
private readonly IJSRuntime jsRuntime;
private bool initialized;
public event EventHandler Changed;
public ReportRepositoryService(IJSRuntime jsRuntime) {
this.jsRuntime = jsRuntime;
}
public async Task SaveReport(ReportRepositoryItem reportRepositoryItem) {
if (reportRepositoryItem is FoundReportRepositoryItem fItem) {
await SaveFoundReport(fItem);
} else if (reportRepositoryItem is MissingReportRepositoryItem mItem) {
await SaveMissingReport(mItem);
}
}
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;
}
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;
}
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<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 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 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);
}
// 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);
}
}
}
}

+ 1
- 3
Shared/Services/UserDataProvider.cs Zobrazit soubor

@@ -6,15 +6,13 @@ using System.Threading.Tasks;
namespace cwebplusApp.Shared.Services {
public sealed class UserDataProvider {
private const string KeyName = "account";
private const string KeyName = "account";
private readonly IJSRuntime _jsRuntime;
private bool _initialized;
public event EventHandler Changed;
public bool AutoSave { get; set; } = true;
public UserDataProvider(IJSRuntime jsRuntime) {
_jsRuntime = jsRuntime;
}

+ 3
- 3
cwebplusApp.csproj Zobrazit soubor

@@ -18,9 +18,9 @@
<PackageReference Include="BlazorGeolocation" Version="0.1.1" />
<PackageReference Include="FisSst.BlazorMaps" Version="1.0.2" />
<PackageReference Include="MatBlazor" Version="2.9.0-develop-042" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.8" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.9" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.9" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
</ItemGroup>

+ 34
- 17
wwwroot/service-worker.js Zobrazit soubor

@@ -20,6 +20,7 @@ const assets = [
'/conclusion_missing',
'/doneimage',
'/failureimage',
'/warningimage',
'favicon.ico',
'images/batch_found.png',
'images/batch_fundvelo.png',
@@ -45,7 +46,7 @@ const assets = [
'_content/blazoranimate/aos.css',
'_framework/blazor.webassembly.js',
'_framework/blazor.boot.json',
'_framework/dotnet.5.0.8.js',
'_framework/dotnet.5.0.9.js',
'https://fonts.googleapis.com/css?family=Roboto:300,400,500',
'https://fonts.googleapis.com/icon?family=Material+Icons',
'https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;700&display=swap',
@@ -86,23 +87,39 @@ self.addEventListener('activate', event => {
});
// fetch events (appsettings are always first fetched from network)
self.addEventListener('fetch', function (event) {
event.respondWith(networkOrCache(event.request).catch(function () {
}));
})
self.addEventListener('fetch', event => {
if (event.request.url.endsWith(appsettings_url)) {
fetch(event.request).then(function (response) {
return caches.open(staticCacheName).then(function (cache) {
console.log('update cache');
cache.put(event.request, response.clone());
return response;
});
}).catch(function () {
return useFallback();
});
} else {
event.respondWith(
caches.match(event.request).then(cacheRes => {
return cacheRes || fetch(event.request);
})
);
}
});
function networkOrCache(request) {
return fetch(request).then(function (response) {
return response.ok ? response : fromCache(request);
}).catch(function () {
return fromCache(request);
});
function useFallback() {
return Promise.resolve(new Response(Appsettings_Fallback, {
headers: {
'Content-Type': 'application/json'
}
}));
}
function fromCache(request) {
return caches.open(staticCacheName).then(function (cache) {
return cache.match(request).then(function (matching) {
return matching || Promise.reject('request-not-in-cache');
});
});
var Appsettings_Fallback = {
"host_base_url": "https://integrate.dynalias.net:9443/Fundvelo/",
"subresource_url_colors": "api/{0}/{1}/fundvelo/colors",
"subresource_url_brands": "api/{0}/{1}/fundvelo/brands",
"subresource_url_types": "api/{0}/{1}/fundvelo/types",
"subresource_url_foundreport": "api/{0}/{1}/fundvelo/fundmeldung",
"subresource_url_missingreport": "api/{0}/{1}/fundvelo/suchauftrag"
}

Načítá se…
Zrušit
Uložit