| @@ -0,0 +1,9 @@ | |||
| @page "/warningimage" | |||
| <div class="text-center"> | |||
| <img src="./images/warning.png" class="w-50" alt="Warning!" /> | |||
| </div> | |||
| @code { | |||
| } | |||
| @@ -16,7 +16,7 @@ | |||
| <div class="row no-gutters align-items-start justify-content-center w-100"> | |||
| <MatHeadline4 Style="font-family:Ubuntu;padding-top:1em">@i18n["Confirmation"]</MatHeadline4> | |||
| </div> | |||
| @if (responseOk) { | |||
| @if (ResposeStatus.OK == responseStatus) { | |||
| <div class="row no-gutters align-items-start justify-content-center w-100" style="height:fit-content"> | |||
| <div class="w-100" style="text-align: center"> | |||
| <MatHeadline6 Style="font-family:Ubuntu">@i18n["FinishedTextFound"]</MatHeadline6> | |||
| @@ -26,26 +26,30 @@ | |||
| </div> | |||
| </div> | |||
| } | |||
| <div class="row no-gutters align-items-start justify-content-center w-100" style="height:fit-content"> | |||
| @if (running) { | |||
| <div style="width:48px;margin:0 auto;"> | |||
| <MatProgressCircle Indeterminate="true" Size="MatProgressCircleSize.Large" /> | |||
| </div> | |||
| <div class="w-100" style="text-align:center;"> | |||
| <h6 style="font-style:italic;padding-bottom:1em">@i18n["Info.Report.Transmitting"]</h6> | |||
| </div> | |||
| <div class="row no-gutters align-items-start justify-content-center w-100" style="height:fit-content"> | |||
| @if (running) { | |||
| <div style="width:48px;margin:0 auto;"> | |||
| <MatProgressCircle Indeterminate="true" Size="MatProgressCircleSize.Large" /> | |||
| </div> | |||
| <div class="w-100" style="text-align:center;"> | |||
| <h6 style="font-style:italic;padding-bottom:1em">@i18n["Info.Report.Transmitting"]</h6> | |||
| </div> | |||
| } else { | |||
| if (ResposeStatus.OK == responseStatus) { | |||
| <Animate Animation="Animations.ZoomIn" Duration="TimeSpan.FromSeconds(2.5)"> | |||
| <DoneImage></DoneImage> | |||
| </Animate> | |||
| } else if (ResposeStatus.Error == responseStatus) { | |||
| <Animate Animation="Animations.ZoomIn" Duration="TimeSpan.FromSeconds(2.5)"> | |||
| <FailureImage></FailureImage> | |||
| </Animate> | |||
| } else { | |||
| if (responseOk) { | |||
| <Animate Animation="Animations.ZoomIn" Duration="TimeSpan.FromSeconds(2.5)"> | |||
| <DoneImage></DoneImage> | |||
| </Animate> | |||
| } else { | |||
| <Animate Animation="Animations.ZoomIn" Duration="TimeSpan.FromSeconds(2.5)"> | |||
| <FailureImage></FailureImage> | |||
| </Animate> | |||
| } | |||
| <Animate Animation="Animations.ZoomIn" Duration="TimeSpan.FromSeconds(2.5)"> | |||
| <WarningImage></WarningImage> | |||
| </Animate> | |||
| } | |||
| </div> | |||
| } | |||
| </div> | |||
| <div class="row no-gutters align-items-end justify-content-center w-100" style="padding-bottom:2em;padding-top:2em"> | |||
| <div class="col w-100 text-center"> | |||
| <MatButton Class="w-50" Raised="true" @onclick="Finished">@i18n["Finished"]</MatButton> | |||
| @@ -56,8 +60,14 @@ | |||
| @code { | |||
| enum ResposeStatus : ushort { | |||
| OK = 1, | |||
| Error = 10, | |||
| NoConnection = 20 | |||
| } | |||
| private Animate doneAnimZoom; | |||
| private bool responseOk = false; | |||
| private ResposeStatus responseStatus = ResposeStatus.NoConnection; | |||
| private bool running = true; | |||
| private string referenceNumber; | |||
| ReportResponse response; | |||
| @@ -67,19 +77,21 @@ | |||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | |||
| try { | |||
| response = await IBicycleRestService.SendFoundReport(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("FoundBike"), new string[] { ex.Message }); | |||
| responseOk = false; | |||
| responseStatus = ResposeStatus.Error; | |||
| } | |||
| running = false; | |||
| if (responseOk) { | |||
| if (ResposeStatus.OK == responseStatus) { | |||
| Toaster.ShowSuccess(i18n.GetString("FoundBike"), response.Message); | |||
| referenceNumber = (response.Data != null && response.Data.Length > 0) ? response.Data[0] : "-"; | |||
| 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")); | |||
| } | |||
| StateHasChanged(); | |||
| AppState.NotifyChanged(); | |||
| @@ -11,6 +11,7 @@ | |||
| @inject Toaster Toaster; | |||
| @inject IConfiguration Configuration; | |||
| @inject IBicycleRestService IBicycleRestService; | |||
| @inject OnlineStatusProvider OnlineStatusProvider; | |||
| <div class="row h-100 justify-content-center"> | |||
| @@ -21,9 +22,9 @@ | |||
| <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) => ButtonClicked())">@i18n["Login"]</MatButton> | |||
| </div> | |||
| @*<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"> | |||
| @@ -51,12 +52,13 @@ | |||
| showProgressCircle = true; | |||
| StateHasChanged(); | |||
| try { | |||
| IBicycleRestService.Initialize(Configuration); | |||
| IBicycleRestService.Initialize(Configuration, OnlineStatusProvider); | |||
| await MasterDataService.SynchronizeMasterdata(); | |||
| } catch (Exception) { | |||
| Toaster.ShowWarning(i18n.GetString("Warning.Masterdata.Title"), i18n.GetString("Warning.Masterdata.Msg")); | |||
| } finally { | |||
| showProgressCircle = false; | |||
| NavigateToNext(); | |||
| } | |||
| } | |||
| btnDisabled = false; | |||
| @@ -64,8 +66,7 @@ | |||
| StateHasChanged(); | |||
| } | |||
| private void ButtonClicked() { | |||
| private void NavigateToNext() { | |||
| NavigationManager.NavigateTo("./caritas_services"); | |||
| AppState.LoggedIn = true; | |||
| } | |||
| } | |||
| @@ -18,7 +18,7 @@ | |||
| <MatAppBarSection> | |||
| <MatIconButton Icon="menu" OnClick="@((e) => ButtonClicked())"></MatIconButton> | |||
| @if (PageHistoryManager.CanGoBack()) { | |||
| <MatIconButton Icon="keyboard_backspace" OnClick="@((e) => ButtonBackClicked())" Disabled="@BackButtonDisabled()"></MatIconButton> | |||
| <MatIconButton Icon="@MatIconNames.Keyboard_backspace" OnClick="@((e) => ButtonBackClicked())" Disabled="@BackButtonDisabled()"></MatIconButton> | |||
| } | |||
| <MatAppBarTitle Class="navBar-title">@LocationUrl</MatAppBarTitle> | |||
| </MatAppBarSection> | |||
| @@ -49,19 +49,19 @@ | |||
| </MatRipple> | |||
| <MatRipple Class="navmenu-mat-ripple" Color="@MatRippleColor.Default"> | |||
| <MatListItem Class="@((Index == 3) ? "bg-primary-color text-white" : "")" Style="margin-left:0;margin-right:0" | |||
| Href="info" | |||
| Disabled="true" | |||
| Href="extras" | |||
| @onclick="@((e) => ButtonClicked(3))"> | |||
| <MatIcon Icon="@MatIconNames.Error_outline" Style="transform: rotate(180deg)"></MatIcon> | |||
| <MatListItemText Style="padding-left:0.5em">@i18n["info"]</MatListItemText> | |||
| <MatIcon Icon="@MatIconNames.View_quilt"></MatIcon> | |||
| <MatListItemText Style="padding-left:0.5em">@i18n["Extras"]</MatListItemText> | |||
| </MatListItem> | |||
| </MatRipple> | |||
| <MatRipple Class="navmenu-mat-ripple" Color="@MatRippleColor.Default"> | |||
| <MatListItem Class="@((Index == 4) ? "bg-primary-color text-white" : "")" Style="margin-left:0;margin-right:0" | |||
| href="" | |||
| Match="NavLinkMatch.All" | |||
| Href="info" | |||
| @onclick="@((e) => ButtonClicked(4))"> | |||
| <MatIcon Icon="@MatIconNames.Exit_to_app"></MatIcon> | |||
| <MatListItemText Style="padding-left:0.5em">@i18n["Logout"]</MatListItemText> | |||
| <MatIcon Icon="@MatIconNames.Error_outline" Style="transform: rotate(180deg)"></MatIcon> | |||
| <MatListItemText Style="padding-left:0.5em">@i18n["info"]</MatListItemText> | |||
| </MatListItem> | |||
| </MatRipple> | |||
| </MatList> | |||
| @@ -95,10 +95,12 @@ | |||
| } | |||
| protected override void OnInitialized() { | |||
| base.OnInitialized(); | |||
| AppState.OnChange += StateHasChanged; | |||
| NavigationManager.LocationChanged += LocationChanged; | |||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | |||
| base.OnInitialized(); | |||
| locUrl = i18n.GetString(NavigationManager.Uri.Replace(NavigationManager.BaseUri, "")); | |||
| StateHasChanged(); | |||
| } | |||
| private void ButtonClicked() { | |||
| @@ -108,9 +110,6 @@ | |||
| private void ButtonClicked(int _Index) { | |||
| Index = _Index; | |||
| ButtonClicked(); | |||
| if (_Index == 4) { | |||
| AppState.LoggedIn = false; | |||
| } | |||
| } | |||
| private void ButtonBackClicked() { | |||
| @@ -125,9 +124,9 @@ | |||
| } else if (e.Location.Contains("account")) { | |||
| Index = 2; | |||
| } else if (e.Location.Contains("info")) { | |||
| Index = 3; | |||
| } else { | |||
| Index = 4; | |||
| } else { | |||
| Index = 3; | |||
| } | |||
| StateHasChanged(); | |||
| } | |||
| @@ -142,19 +141,16 @@ | |||
| string baseUri = NavigationManager.BaseUri; | |||
| string delta = uri.Replace(baseUri, ""); | |||
| if (delta == null || delta.Equals("")) { | |||
| if (delta.Equals("caritas_services")) { | |||
| Index = 1; | |||
| } else if (delta.Equals("account")) { | |||
| Index = 2; | |||
| } else if (delta.Equals("info")) { | |||
| Index = 4; | |||
| return false; | |||
| } else { | |||
| if (delta.Equals("caritas_services")) { | |||
| Index = 1; | |||
| } else if (delta.Equals("account")) { | |||
| Index = 2; | |||
| } else if (delta.Equals("info")) { | |||
| Index = 3; | |||
| } | |||
| return true; | |||
| Index = 3; | |||
| } | |||
| return true; | |||
| } | |||
| private bool BackButtonDisabled() { | |||
| @@ -285,6 +285,9 @@ | |||
| <data name="Error.PhotoOrPictureToBig.Title" xml:space="preserve"> | |||
| <value>Bilddatei zu gross!</value> | |||
| </data> | |||
| <data name="Extras" xml:space="preserve"> | |||
| <value>Extras</value> | |||
| </data> | |||
| <data name="Female" xml:space="preserve"> | |||
| <value>Frau</value> | |||
| </data> | |||
| @@ -447,6 +450,12 @@ | |||
| <data name="Warning.Masterdata.Title" xml:space="preserve"> | |||
| <value>Stammdaten nicht verfügbar!</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Msg" xml:space="preserve"> | |||
| <value>Die Meldung konnte nicht übertragen werde. Sie wurde gespeichert und wird sobald wie möglich übertragen.</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Title" xml:space="preserve"> | |||
| <value>Keine Verbindung zum Internet!</value> | |||
| </data> | |||
| <data name="Warning.Nominatim.Msg" xml:space="preserve"> | |||
| <value>Die Adresse konnte beim Aufrufen des Nominatim-Dienstes nicht aufgelöst werden. Bitte geben Sie die Straße und Postleitzahl/Ort manuell ein.</value> | |||
| </data> | |||
| @@ -285,6 +285,9 @@ | |||
| <data name="Error.PhotoOrPictureToBig.Title" xml:space="preserve"> | |||
| <value>La taille de la photo est trop grande!</value> | |||
| </data> | |||
| <data name="Extras" xml:space="preserve"> | |||
| <value>Extras</value> | |||
| </data> | |||
| <data name="Female" xml:space="preserve"> | |||
| <value>Madame</value> | |||
| </data> | |||
| @@ -447,6 +450,12 @@ | |||
| <data name="Warning.Masterdata.Title" xml:space="preserve"> | |||
| <value>Les données de base ne sont pas disponibles!</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Msg" xml:space="preserve"> | |||
| <value>Le message n'a pas pu être transmis. Il a été sauvegardé et sera transmis dès que possible.</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Title" xml:space="preserve"> | |||
| <value>Pas de connexion à l'internet !</value> | |||
| </data> | |||
| <data name="Warning.Nominatim.Msg" xml:space="preserve"> | |||
| <value>L'adresse n'a pas pu être résolue en invoquant le service Nominatim. Veuillez saisir l'adresse en indiquant la rue et le code postal/ville.</value> | |||
| </data> | |||
| @@ -285,6 +285,9 @@ | |||
| <data name="Error.PhotoOrPictureToBig.Title" xml:space="preserve"> | |||
| <value>Dimensione dell'immagine troppo grande!</value> | |||
| </data> | |||
| <data name="Extras" xml:space="preserve"> | |||
| <value>Extras</value> | |||
| </data> | |||
| <data name="Female" xml:space="preserve"> | |||
| <value>Signora</value> | |||
| </data> | |||
| @@ -447,6 +450,12 @@ | |||
| <data name="Warning.Masterdata.Title" xml:space="preserve"> | |||
| <value>Dati anagrafici non disponibili!</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Msg" xml:space="preserve"> | |||
| <value>Il messaggio non può essere trasmesso. È stato salvato e sarà trasmesso al più presto.</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Title" xml:space="preserve"> | |||
| <value>Nessuna connessione a Internet!</value> | |||
| </data> | |||
| <data name="Warning.Nominatim.Msg" xml:space="preserve"> | |||
| <value>L'indirizzo non può essere risolto invocando il servizio Nominatim. Si prega di digitare la via e CAP/città.</value> | |||
| </data> | |||
| @@ -285,6 +285,9 @@ | |||
| <data name="Error.PhotoOrPictureToBig.Title" xml:space="preserve"> | |||
| <value>Size of picture to big!</value> | |||
| </data> | |||
| <data name="Extras" xml:space="preserve"> | |||
| <value>Extras</value> | |||
| </data> | |||
| <data name="Female" xml:space="preserve"> | |||
| <value>Madam</value> | |||
| </data> | |||
| @@ -447,6 +450,12 @@ | |||
| <data name="Warning.Masterdata.Title" xml:space="preserve"> | |||
| <value>Master data not available!</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Msg" xml:space="preserve"> | |||
| <value>The report could not be transmitted. It was stored and will be transmitted as soon as possible!</value> | |||
| </data> | |||
| <data name="Warning.NoConnection.Title" xml:space="preserve"> | |||
| <value>No connection to the internet!</value> | |||
| </data> | |||
| <data name="Warning.Nominatim.Msg" xml:space="preserve"> | |||
| <value>The address could not be resolved invoking Nominatim service. Please type in the address street and zip/town.</value> | |||
| </data> | |||
| @@ -1,5 +1,4 @@ | |||
| using cwebplusApp.Shared.Models; | |||
| using Microsoft.AspNetCore.Components; | |||
| using Microsoft.Extensions.Configuration; | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| @@ -17,11 +16,12 @@ namespace cwebplusApp.Shared.Services { | |||
| private static readonly string VERSION = "v1"; | |||
| private HttpClient httpClient; | |||
| [Inject] | |||
| public IConfiguration Configuration { get; set; } | |||
| public OnlineStatusProvider OnlineStatusProvider { get; set; } | |||
| public void Initialize(IConfiguration configuration) { | |||
| public void Initialize(IConfiguration configuration, OnlineStatusProvider onlineStatusProvider) { | |||
| this.Configuration = configuration; | |||
| this.OnlineStatusProvider = onlineStatusProvider; | |||
| string hostBaseUrl = Configuration.GetValue<string>("host_base_url"); | |||
| if (!String.IsNullOrEmpty(hostBaseUrl)) { | |||
| this.httpClient = new HttpClient { BaseAddress = new Uri(hostBaseUrl) }; | |||
| @@ -87,18 +87,23 @@ namespace cwebplusApp.Shared.Services { | |||
| } | |||
| 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; | |||
| if (OnlineStatusProvider.Online) { | |||
| 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!"); | |||
| } else { | |||
| //TODO: Save to app storage | |||
| return null; | |||
| } | |||
| throw new HttpRequestException("HTTP client not initialized!"); | |||
| } | |||
| } | |||
| } | |||
| @@ -6,7 +6,7 @@ using System.Threading.Tasks; | |||
| namespace cwebplusApp.Shared.Services { | |||
| public interface IBicycleRestService { | |||
| void Initialize(IConfiguration configuration); | |||
| void Initialize(IConfiguration configuration, OnlineStatusProvider onlineStatusProvider); | |||
| Task<List<ColorItem>> GetColors(); | |||
| @@ -29,6 +29,8 @@ const assets = [ | |||
| 'images/caritas_logo.png', | |||
| 'images/integrate_logo.png', | |||
| 'images/done.png', | |||
| 'images/failure.png', | |||
| 'images/warning.png', | |||
| 'images/icon_camera.png', | |||
| 'images/icon_driveupload.png', | |||
| 'images/icon_location.png', | |||
| @@ -84,68 +86,23 @@ self.addEventListener('activate', event => { | |||
| }); | |||
| // fetch events (appsettings are always first fetched from network) | |||
| 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 () { | |||
| var cr; | |||
| console.log('catch network fetch failure 1'); | |||
| event.waitUntil( | |||
| caches.match(event.request).then(cacheRes => { | |||
| console.log('catch network fetch failure 2'); | |||
| console.log(cacheRes); | |||
| cr = cacheRes; | |||
| }) | |||
| ); | |||
| console.log('catch network fetch failure 3'); | |||
| console.log(cr); | |||
| return cr; | |||
| //fromCache(event.request); | |||
| }) | |||
| } else { | |||
| event.respondWith( | |||
| caches.match(event.request).then(cacheRes => { | |||
| return cacheRes || fetch(event.request); | |||
| }) | |||
| ); | |||
| } | |||
| }); | |||
| //self.addEventListener('fetch', event => { | |||
| // if (event.request.url.endsWith(appsettings_url)) { | |||
| // networkOrCache(event.request); | |||
| // } else { | |||
| // event.respondWith( | |||
| // caches.match(event.request).then(cacheRes => { | |||
| // return cacheRes || fetch(event.request); | |||
| // }) | |||
| // ); | |||
| // } | |||
| //}); | |||
| self.addEventListener('fetch', function (event) { | |||
| event.respondWith(networkOrCache(event.request).catch(function () { | |||
| })); | |||
| }) | |||
| //function networkOrCache(request) { | |||
| // return fetch(request).then(function (response) { | |||
| // caches.open(staticCacheName).then(function (cache) { | |||
| // console.log('update cache'); | |||
| // cache.put(request, response.clone()); | |||
| // }); | |||
| // return response.ok ? response : fromCache(request); | |||
| // //}).catch(function () { | |||
| // // return fromCache(request); | |||
| // }); | |||
| //} | |||
| function networkOrCache(request) { | |||
| return fetch(request).then(function (response) { | |||
| return response.ok ? response : fromCache(request); | |||
| }).catch(function () { | |||
| return fromCache(request); | |||
| }); | |||
| } | |||
| //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'); | |||
| // }); | |||
| // }); | |||
| //} | |||
| 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'); | |||
| }); | |||
| }); | |||
| } | |||