| @@ -44,6 +44,12 @@ | |||
| OnKeyDown="@InputCursorHandler.OnKeyDownHandlerAsync" maxlength="50"></MatStringField> | |||
| </div> | |||
| </div> | |||
| <div class="row no-gutters align-items-center w-100"> | |||
| <div class="col-12"> | |||
| <MatStringField Class="w-100" Label="@I18n["Postbox"]" Outlined="true" type="text" @bind-Value="@Account.Postbox" | |||
| OnKeyDown="@InputCursorHandler.OnKeyDownHandlerAsync" maxlength="50"></MatStringField> | |||
| </div> | |||
| </div> | |||
| <div class="row no-gutters align-items-center w-100"> | |||
| <div class="col-12"> | |||
| <div class="outlined"> | |||
| @@ -135,8 +141,12 @@ | |||
| if (!string.IsNullOrEmpty(FromRoute) && ReportDataProvider.Report != null) { | |||
| UserDataProvider.MapUserData(Account, ReportDataProvider.Report); | |||
| } | |||
| setZipCityValue(Account.Zip + " " + Account.City); | |||
| SelectedZipCity = Array.Find(ZipCities, zipCity => (zipCity.Zip.Equals(Account.Zip) && zipCity.City.Equals(Account.City))); | |||
| var combinedValue = Account.Zip + " " + Account.City; | |||
| setZipCityValue(combinedValue); | |||
| if (ZipCities == null) | |||
| SelectedZipCity = new ZipCity(combinedValue); | |||
| else | |||
| SelectedZipCity = Array.Find(ZipCities, zipCity => (zipCity.Zip.Equals(Account.Zip) && zipCity.City.Equals(Account.City))); | |||
| StateHasChanged(); | |||
| } | |||
| @@ -160,8 +170,8 @@ | |||
| private async void SaveUserDataAndClose() { | |||
| try { | |||
| Account.Zip = SelectedZipCity.Zip; | |||
| Account.City = SelectedZipCity.City; | |||
| Account.Zip = SelectedZipCity == null ? null : SelectedZipCity.Zip; | |||
| Account.City = SelectedZipCity == null ? null : SelectedZipCity.City; | |||
| Validator.ValidateAccount(Account); | |||
| await UserDataProvider.Save(Account); | |||
| Toaster.ShowSuccess(I18n.GetString("Success.SaveUserdata.Title"), I18n.GetString("Success.SaveUserdata.Msg")); | |||
| @@ -3,6 +3,7 @@ | |||
| @using cwebplusApp.Shared.Services; | |||
| @using cwebplusApp.Shared.Models; | |||
| @using cwebplusApp.Components; | |||
| @using System.Text.RegularExpressions; | |||
| @inject NavigationManager NavigationManager; | |||
| @inject IStringLocalizer<Resources> I18n; | |||
| @@ -102,7 +103,8 @@ | |||
| if (ResponseStatus.OK == responseStatus) { | |||
| Toaster.ShowSuccess(I18n.GetString("FoundBike"), response.Message); | |||
| referenceNumber = (response.Data != null && response.Data.Length > 0) ? response.Data[0] : "-"; | |||
| referenceNumber = Regex.Match(response.Message, "[A-Z]{2}[0-9]{10}").Value; | |||
| referenceNumber = (referenceNumber != null && referenceNumber.Length > 0) ? referenceNumber : "-"; | |||
| PageHistoryManager.Reset(); | |||
| } else if (ResponseStatus.Error == responseStatus) { | |||
| Toaster.ShowError(response.Message, response.GetDataAsFormattedList()); | |||
| @@ -73,32 +73,32 @@ | |||
| </div> | |||
| </div> | |||
| @if (OnlineStatusProvider.Online) { | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-1 justify-content-center" style="text-align: center"> | |||
| @if (PermissionsProvider.IsGeoLocationAllowed) { | |||
| <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 class="mat-layout-grid-cell mat-layout-grid-cell-span-1 justify-content-center" style="text-align: center"> | |||
| @if (IsGeoLocationAllowed) { | |||
| <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 class="mat-layout-grid-cell mat-layout-grid-cell-span-3"> | |||
| <div class="w-100 fv-osm-tile map-wrapper"> | |||
| <Map @ref="mapRef" MapOptions="@mapOptions" AfterRender="AfterRenderMap"></Map> | |||
| @@ -174,31 +174,33 @@ | |||
| </div> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-3-tablet mat-layout-grid-cell-span-3-desktop"> | |||
| <MatSelectValue Class="required" FullWidth="true" Outlined="true" Label="@I18n["Type"]" @bind-Value="selectedBcType" Items="@BicycleTypes" ValueSelector="@(i=>i)" | |||
| @onkeydown="InputCursorHandler.OnKeyDownHandlerAsync"> | |||
| <ItemTemplate> | |||
| <div> | |||
| <span>@context?.Bezeichnung</span> | |||
| </div> | |||
| </ItemTemplate> | |||
| </MatSelectValue> | |||
| <div class="outlined"> | |||
| <MatAutocompleteList TItem="BicycleType" FullWidth="true" Label="@I18n["Type"]" Required="true" Items="@BicycleTypes" OnTextChanged="setBcTypeValue" @bind-Value="SelectedBcType" CustomStringSelector="@(i=>i?.Bezeichnung)" | |||
| ShowClearButton="true" NumberOfElementsInPopup="6" @onkeydown="InputCursorHandler.OnKeyDownHandlerAsync"> | |||
| <ItemTemplate> | |||
| <div> | |||
| <span>@context?.Bezeichnung</span> | |||
| </div> | |||
| </ItemTemplate> | |||
| </MatAutocompleteList> | |||
| </div> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-3-tablet mat-layout-grid-cell-span-3-desktop"> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-12-desktop"> | |||
| <MatStringField Class="w-100 form-check-label" Label="@I18n["FrameNumber"]" Outlined="true" type="text" @bind-Value="frameNumber" | |||
| OnKeyDown="@InputCursorHandler.OnKeyDownHandlerAsync" maxlength="20"></MatStringField> | |||
| OnKeyDown="@InputCursorHandler.OnKeyDownHandlerAsync" maxlength="20"></MatStringField> | |||
| </div> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-12-phone mat-layout-grid-cell-span-12-tablet mat-layout-grid-cell-span-12-desktop"> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-12-desktop"> | |||
| <MatStringField Class="w-100 form-check-label" Label="@I18n["Remark"]" Outlined="true" type="text" @bind-Value="remark" | |||
| OnKeyDown="@InputCursorHandler.OnKeyDownHandlerAsync" maxlength="1000" rows="1" TextArea="true"></MatStringField> | |||
| OnKeyDown="@InputCursorHandler.OnKeyDownHandlerAsync" maxlength="1000" rows="1" TextArea="true"></MatStringField> | |||
| </div> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-4-desktop"> | |||
| <div> | |||
| <MatCheckbox @bind-Value="@abholadresseIsNotContact" Label="@I18n["AlternatePickupContact"]" | |||
| @onkeydown="InputCursorHandler.OnKeyDownHandlerAsync"></MatCheckbox> | |||
| @onkeydown="InputCursorHandler.OnKeyDownHandlerAsync"></MatCheckbox> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -224,7 +226,8 @@ | |||
| private string imgUrl = string.Empty; | |||
| private Boolean loading = false; | |||
| private ColorItem selectedColor; | |||
| private BicycleType selectedBcType; | |||
| private bool IsGeoLocationAllowed = false; | |||
| private string brandStringValue; | |||
| private Brand selectedBrand; | |||
| private Brand SelectedBrand { | |||
| @@ -236,6 +239,16 @@ | |||
| selectedBrand = null; | |||
| } | |||
| private string bcTypeStringValue; | |||
| private BicycleType selectedBcType; | |||
| private BicycleType SelectedBcType { | |||
| get { return selectedBcType; } | |||
| set { selectedBcType = (value != null) ? value : new BicycleType(-999, bcTypeStringValue); } | |||
| } | |||
| private void setBcTypeValue(string value) { | |||
| bcTypeStringValue = value; | |||
| } | |||
| private string zipCityStringValue; | |||
| private ZipCity selectedZipCity; | |||
| private ZipCity SelectedZipCity { | |||
| @@ -263,6 +276,7 @@ | |||
| await GetZipCities(); | |||
| RefreshGUIFromDto(); | |||
| OnlineStatusProvider.AddOnlineStatusChangeCallBack(OnOnlineStatusChanged); | |||
| PermissionsProvider.SetGeoLocationPermissionChangeCallBack(OnGeoLocationPermissionChanged); | |||
| StateHasChanged(); | |||
| } | |||
| @@ -270,6 +284,14 @@ | |||
| StateHasChanged(); | |||
| } | |||
| private async void OnGeoLocationPermissionChanged(bool allowed) { | |||
| IsGeoLocationAllowed = allowed; | |||
| MouseEvent mouseEvent = new MouseEvent(); | |||
| mouseEvent.LatLng = await InitializeDeviceMapPosition(); | |||
| await OnMouseMapClicked(mouseEvent); | |||
| StateHasChanged(); | |||
| } | |||
| private async void AfterRenderMap() { | |||
| FoundReport report = ReportDataProvider.GetFoundReport(); | |||
| MouseEvent mouseEvent = new MouseEvent(); | |||
| @@ -109,15 +109,19 @@ namespace cwebplusApp.Pages { | |||
| } | |||
| protected async Task<LatLng> GetDeviceGeoLocation() { | |||
| Console.WriteLine("GetDeviceGeoLocation..."); | |||
| LatLng geoPosition = new(46.80121, 8.22669); // Centered on Swiss | |||
| if (PermissionsProvider.IsGeoLocationAllowed) { | |||
| Console.WriteLine("GetDeviceGeoLocation - THEN"); | |||
| BlazorGeolocationPosition position = await this.BlazorGeolocationService.GetPositionAsync(); | |||
| if (position.ErrorCode != null) { | |||
| Console.WriteLine("GetDeviceGeoLocation - THEN -ERROR"); | |||
| Toaster.ShowError(I18n.GetString("Error.GeoLocation.Title", position.ErrorCode), I18n.GetString("Error.GeoLocation.Msg", position.ErrorMessage)); | |||
| } else { | |||
| geoPosition = new((double)position.Latitude, (double)position.Longitude); | |||
| } | |||
| } else { | |||
| Console.WriteLine("GetDeviceGeoLocation - ELSE"); | |||
| Toaster.ShowWarning(I18n.GetString("Warning.Permission.GeoLocation.Title"), I18n.GetString("Warning.Permission.GeoLocation.Msg")); | |||
| } | |||
| return geoPosition; | |||
| @@ -19,6 +19,29 @@ | |||
| <td class="text-center"> | |||
| <span class="text-left" style="max-width: 500px;display:inline-block;font-size:smaller"> | |||
| <pre style="white-space:pre-line;font-family:'Ubuntu';margin-bottom:0">@I18n["App.Info"]</pre> | |||
| </span> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td class="text-center"> | |||
| <span class="text-left" style="max-width: 500px;display:inline-block;font-size:smaller"> | |||
| <pre style="white-space:pre-line;font-family:'Ubuntu';margin-bottom:0">@I18n["App.Info.Fundvelo"]</pre> | |||
| <p> | |||
| <a href="https://shop.caritas-luzern.ch/de/Velos-c75735006" target="_blank">Velos (caritas-luzern.ch)</a> | |||
| <br /> | |||
| <a href="https://www.velostation.ch/de/velostationen/uebersichtskarte/luzern" target="_blank">Luzern – Forum Velostationen Schweiz</a> | |||
| <br /> | |||
| <a href="https://www.nextbike.ch/de/" target="_blank">nextbike | Fahrradverleih in Luzern</a> | |||
| <br /> | |||
| <a href="https://www.caritas-luzern.ch/was-wir-tun/caritas-betriebe/velomobilitaet-velodienste-velowerkstatt-veloverleih" target="_blank">Velodienste, Velowerkstatt & Veloverleih</a> | |||
| </p> | |||
| </span> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td class="text-center"> | |||
| <span class="text-left" style="max-width: 500px;display:inline-block;font-size:smaller"> | |||
| <pre style="white-space:pre-line;font-family:'Ubuntu';margin-bottom:0">@I18n["App.Info.KuLe"]</pre> | |||
| <p><a href="https://www.kulturlegi.ch" target="_blank">https://www.kulturlegi.ch</a></p> | |||
| </span> | |||
| </td> | |||
| @@ -5,6 +5,7 @@ | |||
| private string firstname; | |||
| private string lastname; | |||
| private string address; | |||
| private string postbox; | |||
| private string zip; | |||
| private string city; | |||
| private string phone; | |||
| @@ -15,6 +16,7 @@ | |||
| public string Firstname { get => firstname; set { firstname = value; } } | |||
| public string Lastname { get => lastname; set { lastname = value; } } | |||
| public string Address { get => address; set { address = value; } } | |||
| public string Postbox { get => postbox; set { postbox = value; } } | |||
| public string Zip { get => zip; set { zip = value; } } | |||
| public string City { get => city; set { city = value; } } | |||
| public string Phone { get => phone; set { phone = value; } } | |||
| @@ -68,9 +68,6 @@ | |||
| <MatNavItem Href="fundvelo/history_missing" AllowSelection="true" Class="@((index == 4)? "selected": "")" @onclick="@((e) => ButtonClicked(4))"> | |||
| <MatIcon Icon="@MatIconNames.History" /> @I18n["HistoryMissing"] | |||
| </MatNavItem> | |||
| <MatNavItem Href="fundvelo/links" AllowSelection="true" Class="@((index == 5)? "selected": "")" @onclick="@((e) => ButtonClicked(5))"> | |||
| <MatIcon Icon="@MatIconNames.Link" /> @I18n["FundveloLinks"] | |||
| </MatNavItem> | |||
| </MatNavSubMenuList> | |||
| </MatNavSubMenu> | |||
| </MatNavSubMenuList> | |||
| @@ -133,14 +133,14 @@ | |||
| <value>Abweichender Abholkontakt</value> | |||
| </data> | |||
| <data name="App.Info" xml:space="preserve"> | |||
| <value>Die Cweb+ App ist eine eigenständige Mobile-App. Sie ist integraler Bestandteil der Applikation/Plattform von Caritas. | |||
| Fundvelo: | |||
| Dieser Dienst ermöglicht es Bürgern und Behörden auf einfachste Art und Weise Velos zu melden, welche vermutlich gestohlen wurden. Wenn man selbst ein Velo vermisst, so soll die App die wichtigsten Infos zusammenfassen, wo/wie man eventuell wieder an sein Velo kommt. Somit ergeben sich zwei Funktionen: | |||
| • Velo gefunden | |||
| • Velo vermisst | |||
| KulturLegi: | |||
| <value>Die Cweb+ App ist eine eigenständige Mobile-App. Sie ist integraler Bestandteil der Applikation/Plattform von Caritas.</value> | |||
| </data> | |||
| <data name="App.Info.Fundvelo" xml:space="preserve"> | |||
| <value>Fundvelo: | |||
| Dieser Dienst ermöglicht es Bürgern und Behörden auf einfachste Art und Weise Velos zu melden, welche vermutlich gestohlen wurden. Wenn man selbst ein Velo vermisst, so soll die App die wichtigsten Infos zusammenfassen, wo/wie man eventuell wieder an sein Velo kommt.</value> | |||
| </data> | |||
| <data name="App.Info.KuLe" xml:space="preserve"> | |||
| <value>KulturLegi: | |||
| Armut führt häufig zu einer eingeschränkten Teilnahme am gesellschaftlichen und kulturellen Leben bis hin zu sozialer Isolation. | |||
| Die KulturLegi wirkt dem entgegen indem sie Kultur-, Bildungs- und Sportangebote für Menschen an der Armutsgrenze erschwinglich macht und so ihre Integration in das gesellschaftliche Leben fördert. Dieser Dienst ermöglicht das Anfordern und Verwalten der KulturLegi in elektronischer Form.</value> | |||
| </data> | |||
| @@ -462,6 +462,9 @@ Die KulturLegi wirkt dem entgegen indem sie Kultur-, Bildungs- und Sportangebote | |||
| <data name="PlaceOfLoss" xml:space="preserve"> | |||
| <value>Verlustort</value> | |||
| </data> | |||
| <data name="Postbox" xml:space="preserve"> | |||
| <value>Postfach</value> | |||
| </data> | |||
| <data name="Price" xml:space="preserve"> | |||
| <value>Preis</value> | |||
| </data> | |||
| @@ -133,14 +133,14 @@ | |||
| <value>Contact de ramassage déviant</value> | |||
| </data> | |||
| <data name="App.Info" xml:space="preserve"> | |||
| <value>L'application Cweb+ est une application mobile autonome. Il fait partie intégrante de l'application/plateforme Caritas. | |||
| Vélo perdu et trouvé : | |||
| Ce service permet aux citoyens et aux autorités de signaler facilement les bicyclettes suspectées d'avoir été volées. Si vous avez vous-même perdu un vélo, l'application doit résumer les informations les plus importantes sur le lieu et la manière dont vous pouvez éventuellement récupérer votre vélo. Il en résulte deux fonctions : | |||
| • Signaler un vélo trouvé | |||
| • Soumettre une demande de recherche pour vélo manquant | |||
| KulturLegi : | |||
| <value>L'application Cweb+ est une application mobile autonome. Il fait partie intégrante de l'application/plateforme Caritas.</value> | |||
| </data> | |||
| <data name="App.Info.Fundvelo" xml:space="preserve"> | |||
| <value>Vélo perdu et trouvé : | |||
| Ce service permet aux citoyens et aux autorités de signaler facilement les bicyclettes suspectées d'avoir été volées. Si vous avez vous-même perdu un vélo, l'application doit résumer les informations les plus importantes sur le lieu et la manière dont vous pouvez éventuellement récupérer votre vélo.</value> | |||
| </data> | |||
| <data name="App.Info.KuLe" xml:space="preserve"> | |||
| <value>KulturLegi : | |||
| La pauvreté entraîne souvent une participation limitée à la vie sociale et culturelle, voire un isolement social. | |||
| La KulturLegi s'attaque à ce problème en rendant les activités culturelles, éducatives et sportives abordables pour les personnes sous le seuil de pauvreté, favorisant ainsi leur intégration dans la vie sociale. Ce service permet de demander et de gérer la KulturLegi sous forme électronique.</value> | |||
| </data> | |||
| @@ -462,6 +462,9 @@ La KulturLegi s'attaque à ce problème en rendant les activités culturelles, | |||
| <data name="PlaceOfLoss" xml:space="preserve"> | |||
| <value>Lieu de la perte</value> | |||
| </data> | |||
| <data name="Postbox" xml:space="preserve"> | |||
| <value>Boîte postale</value> | |||
| </data> | |||
| <data name="Price" xml:space="preserve"> | |||
| <value>Prix</value> | |||
| </data> | |||
| @@ -133,14 +133,14 @@ | |||
| <value>Contatto di prelievo deviante</value> | |||
| </data> | |||
| <data name="App.Info" xml:space="preserve"> | |||
| <value>L'applicazione Cweb+ è un'applicazione mobile indipendente. È parte integrante dell'app/piattaforma Caritas. | |||
| Bici persa e ritrovata: | |||
| Questo servizio permette ai cittadini e alle autorità di segnalare facilmente le biciclette che si sospetta siano state rubate. Se tu stesso hai perso una bici, l'app dovrebbe riassumere le informazioni più importanti su dove/come puoi eventualmente recuperare la tua bici. Questo si traduce in due funzioni: | |||
| • Segnala il ritrovamento di una bicicletta | |||
| • Invia una richiesta di ricerca per bicicletta scomparsa | |||
| KulturLegi: | |||
| <value>L'applicazione Cweb+ è un'applicazione mobile indipendente. È parte integrante dell'app/piattaforma Caritas.</value> | |||
| </data> | |||
| <data name="App.Info.Fundvelo" xml:space="preserve"> | |||
| <value>Bici persa e ritrovata: | |||
| Questo servizio permette ai cittadini e alle autorità di segnalare facilmente le biciclette che si sospetta siano state rubate. Se tu stesso hai perso una bici, l'app dovrebbe riassumere le informazioni più importanti su dove/come puoi eventualmente recuperare la tua bici. </value> | |||
| </data> | |||
| <data name="App.Info.KuLe" xml:space="preserve"> | |||
| <value>KulturLegi: | |||
| La povertà porta spesso a una partecipazione limitata alla vita sociale e culturale e persino all'isolamento sociale. | |||
| La KulturLegi si oppone a questo rendendo le attività culturali, educative e sportive accessibili alle persone sulla soglia di povertà, promuovendo così la loro integrazione nella vita sociale. Questo servizio permette di richiedere e gestire la KulturLegi in forma elettronica.</value> | |||
| </data> | |||
| @@ -462,6 +462,9 @@ La KulturLegi si oppone a questo rendendo le attività culturali, educative e sp | |||
| <data name="PlaceOfLoss" xml:space="preserve"> | |||
| <value>Luogo della perdita</value> | |||
| </data> | |||
| <data name="Postbox" xml:space="preserve"> | |||
| <value>Casella postale</value> | |||
| </data> | |||
| <data name="Price" xml:space="preserve"> | |||
| <value>Prezzo</value> | |||
| </data> | |||
| @@ -133,14 +133,14 @@ | |||
| <value>Alternate Pickup Contact</value> | |||
| </data> | |||
| <data name="App.Info" xml:space="preserve"> | |||
| <value>The Cweb+ app is a standalone mobile app. It is an integral part of the Caritas app/platform. | |||
| Lost and Found Bike: | |||
| This service allows citizens and authorities to easily report bikes that are suspected to have been stolen. If you are missing a bike yourself, the app should summarise the most important information on where/how you can possibly get your bike back. This results in two functions: | |||
| • Report a found bike | |||
| • Submit search request for missing bike | |||
| KulturLegi: | |||
| <value>The Cweb+ app is a standalone mobile app. It is an integral part of the Caritas app/platform.</value> | |||
| </data> | |||
| <data name="App.Info.Fundvelo" xml:space="preserve"> | |||
| <value>Lost and Found Bike: | |||
| This service allows citizens and authorities to easily report bikes that are suspected to have been stolen. If you are missing a bike yourself, the app should summarise the most important information on where/how you can possibly get your bike back.</value> | |||
| </data> | |||
| <data name="App.Info.KuLe" xml:space="preserve"> | |||
| <value>KulturLegi: | |||
| Poverty often leads to limited participation in social and cultural life and even to social isolation. | |||
| The KulturLegi counteracts this by making cultural, educational and sporting activities affordable for people on the poverty line, thus promoting their integration into social life. This service makes it possible to apply for and manage the KulturLegi in electronic form.</value> | |||
| </data> | |||
| @@ -507,6 +507,9 @@ The KulturLegi counteracts this by making cultural, educational and sporting act | |||
| <data name="Street" xml:space="preserve"> | |||
| <value>Street</value> | |||
| </data> | |||
| <data name="String" xml:space="preserve"> | |||
| <value>P.O Box</value> | |||
| </data> | |||
| <data name="Success.DeleteReport.Msg" xml:space="preserve"> | |||
| <value>The Report with ID {0:d} was successfully deleted!</value> | |||
| </data> | |||
| @@ -313,17 +313,17 @@ namespace cwebplusApp.Shared.Services { | |||
| } | |||
| private static List<ColorItem> SortColors(List<ColorItem> colors) { | |||
| colors.Sort(delegate (ColorItem c1, ColorItem c2) { return c1.Id == 0 ? -1 : c2.Id == 0 ? 1 : c1.Bezeichnung.CompareTo(c2.Bezeichnung); }); | |||
| colors.Sort(delegate (ColorItem c1, ColorItem c2) { return c1.Id == 0 ? 1 : c2.Id == 0 ? -1 : c1.Bezeichnung.CompareTo(c2.Bezeichnung); }); | |||
| return colors; | |||
| } | |||
| private static List<BicycleType> SortBicycleTypes(List<BicycleType> bcTypes) { | |||
| bcTypes.Sort(delegate (BicycleType bct1, BicycleType bct2) { return bct1.Id == 0 ? -1 : bct2.Id == 0 ? 1 : bct1.Bezeichnung.CompareTo(bct2.Bezeichnung); }); | |||
| bcTypes.Sort(delegate (BicycleType bct1, BicycleType bct2) { return bct1.Id == 0 ? 1 : bct2.Id == 0 ? -1 : bct1.Bezeichnung.CompareTo(bct2.Bezeichnung); }); | |||
| return bcTypes; | |||
| } | |||
| private static List<Brand> SortBrands(List<Brand> brands) { | |||
| brands.Sort(delegate (Brand b1, Brand b2) { return b1.Id == 0 ? -1 : b2.Id == 0 ? 1 : b1.Bezeichnung.CompareTo(b2.Bezeichnung); }); | |||
| brands.Sort(delegate (Brand b1, Brand b2) { return b1.Id == 0 ? 1 : b2.Id == 0 ? -1 : b1.Bezeichnung.CompareTo(b2.Bezeichnung); }); | |||
| return brands; | |||
| } | |||
| @@ -51,7 +51,6 @@ namespace cwebplusApp.Shared.Services { | |||
| notValid += String.IsNullOrEmpty(report.Anrede) ? 1 : 0; | |||
| notValid += String.IsNullOrEmpty(report.Vorname) ? 1 : 0; | |||
| notValid += String.IsNullOrEmpty(report.Nachname) ? 1 : 0; | |||
| notValid += String.IsNullOrEmpty(report.Telefon) ? 1 : 0; | |||
| if (notValid > 0) { | |||
| throw new ArgumentException("ValidationException"); | |||
| } | |||
| @@ -1,33 +1,60 @@ | |||
| using Microsoft.JSInterop; | |||
| using System; | |||
| using System.Threading.Tasks; | |||
| namespace cwebplusApp.Shared.Services { | |||
| public class PermissionsProvider { | |||
| private bool _isGeoLocationAllowed; | |||
| public delegate void GeoLocationPermissionChangeCallBack(bool allowed); | |||
| private GeoLocationPermissionChangeCallBack _geoLocationPermissionChangeCallBack; | |||
| public IJSRuntime JSRuntime { get; set; } | |||
| public bool IsGeoLocationAllowed { get; set; } | |||
| public bool IsGeoLocationAllowed { | |||
| get { | |||
| Console.WriteLine("IsGeoLocationAllowed.Get {0}", _isGeoLocationAllowed); | |||
| return _isGeoLocationAllowed; | |||
| } | |||
| set { | |||
| Console.WriteLine("IsGeoLocationAllowed.Set {0}", value); | |||
| _isGeoLocationAllowed = value; | |||
| } | |||
| } | |||
| public PermissionsProvider(IJSRuntime _jSRuntime) { | |||
| this.JSRuntime = _jSRuntime; | |||
| initialize(); | |||
| initialize(); | |||
| } | |||
| [JSInvokable] | |||
| public void GeoLocationPermissionChanged(string geoLocationStatus) { | |||
| IsGeoLocationAllowed = (geoLocationStatus.Equals("granted") || geoLocationStatus.Equals("prompt")) ? true : false; | |||
| this._geoLocationPermissionChangeCallBack(IsGeoLocationAllowed); | |||
| } | |||
| public void SetGeoLocationPermissionChangeCallBack(GeoLocationPermissionChangeCallBack callback) { | |||
| this._geoLocationPermissionChangeCallBack = callback; | |||
| } | |||
| public void RemoveOnlineStatusChangeCallBack() { | |||
| this._geoLocationPermissionChangeCallBack = null; | |||
| } | |||
| private async void initialize() { | |||
| Console.WriteLine("PermissionsProvider.initialize"); | |||
| await GeoLocationAllowed(); | |||
| } | |||
| private async Task<bool> GeoLocationAllowed() { | |||
| string result = ""; | |||
| Console.WriteLine("PermissionsProvider.GeoLocationAllowed"); | |||
| var dotNetObjRef = DotNetObjectReference.Create(this); | |||
| result = await JSRuntime.InvokeAsync<string>("IsGeoLocationAllowed", dotNetObjRef); | |||
| string result = await JSRuntime.InvokeAsync<string>("IsGeoLocationAllowed", dotNetObjRef); | |||
| this.IsGeoLocationAllowed = result.Equals("granted") || result.Equals("prompt"); | |||
| Console.WriteLine("PermissionsProvider.GeoLocationAllowed result={0}", result); | |||
| return IsGeoLocationAllowed; | |||
| } | |||
| @@ -87,6 +87,7 @@ namespace cwebplusApp.Shared.Services { | |||
| report.PersonOrt = userData.City; | |||
| report.PersonPLZ = userData.Zip; | |||
| report.PersonStrasse = userData.Address; | |||
| report.Postfach = userData.Postbox; | |||
| report.Mobil = userData.Mobile; | |||
| report.Mail = userData.Email; | |||
| } | |||
| @@ -10,7 +10,7 @@ | |||
| <PropertyGroup> | |||
| <TargetFramework>net5.0</TargetFramework> | |||
| <ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest> | |||
| <Version>0.9.9</Version> | |||
| <Version>0.9.14</Version> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| @@ -1,8 +1,9 @@ | |||
| { | |||
| //"host_base_url": "http://localhost:63733/", | |||
| //"host_base_url": "https://vm-caritas/Fundvelo/", | |||
| "host_base_url": "https://integrate.dynalias.net:9443/Fundvelo/", | |||
| //"host_base_url": "https://cwebplus.ch/Fundvelo/", | |||
| //"host_base_url": "https://integrate.dynalias.net:9443/Fundvelo/", | |||
| //"host_base_url": "https://81.62.196.222:9443/Fundvelo/", | |||
| "host_base_url": "https://cwebplus.ch/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", | |||
| @@ -28,9 +28,9 @@ | |||
| <body> | |||
| <app>App wird geladen...</app> | |||
| <div id="blazor-error-ui"> | |||
| Unbehandelter Fehler ist aufgetreten. | |||
| Ein unbehandelter Fehler ist aufgetreten. | |||
| <a href="" class="reload">Neu laden</a> | |||
| <a class="dismiss">🗙</a> | |||
| </div> | |||
| @@ -126,16 +126,34 @@ | |||
| } | |||
| function IsGeoLocationAllowed(dotNetObjRef) { | |||
| navigator.permissions.query({ name: 'geolocation' }).then(function (result) { | |||
| console.log("GeoLocation permission: " + result.state); | |||
| result.onchange = function () { | |||
| console.log("IsGeoLocationAllowed..."); | |||
| if (isSafari()) { | |||
| navigator.geolocation.getCurrentPosition( | |||
| position => { | |||
| console.log("IsGeoLocationAllowed.position"); | |||
| // this function is called only if the user grant permission so here you can handle the granted state | |||
| dotNetObjRef.invokeMethodAsync("GeoLocationPermissionChanged", "granted"); | |||
| return "granted"; | |||
| }, | |||
| error => { | |||
| console.log("IsGeoLocationAllowed.error"); | |||
| // this function is called if the user denied permission or some other errors occurs | |||
| dotNetObjRef.invokeMethodAsync("GeoLocationPermissionChanged", "denied"); | |||
| return "denied"; | |||
| } | |||
| ); | |||
| } | |||
| else { | |||
| navigator.permissions.query({ name: 'geolocation' }).then(function (result) { | |||
| console.log("GeoLocation permission: " + result.state); | |||
| result.onchange = function () { | |||
| console.log("GeoLocation permission: " + result.state); | |||
| dotNetObjRef.invokeMethodAsync("GeoLocationPermissionChanged", result.state); | |||
| } | |||
| dotNetObjRef.invokeMethodAsync("GeoLocationPermissionChanged", result.state); | |||
| } | |||
| dotNetObjRef.invokeMethodAsync("GeoLocationPermissionChanged", result.state); | |||
| return result.state; | |||
| }); | |||
| return result.state; | |||
| }); | |||
| } | |||
| return ""; | |||
| } | |||
| @@ -229,12 +247,20 @@ | |||
| }); | |||
| } | |||
| function iOSInstallerCheck() { | |||
| function isSafari() { | |||
| console.log("isSafari..."); | |||
| var is_safari = navigator.userAgent.toLowerCase().indexOf('safari/') > -1; | |||
| return is_safari; | |||
| } | |||
| function isIOS() { | |||
| console.log("isIOS..."); | |||
| // Detects if device is on iOS | |||
| const isIOS = () => { | |||
| const userAgent = window.navigator.userAgent.toLowerCase(); | |||
| return /iphone|ipad|ipod/.test(userAgent); | |||
| } | |||
| const userAgent = window.navigator.userAgent.toLowerCase(); | |||
| return /iphone|ipad|ipod/.test(userAgent); | |||
| } | |||
| function iOSInstallerCheck() { | |||
| // Detects if device is in standalone mode | |||
| const isInStandaloneMode = () => ('standalone' in window.navigator) && (window.navigator.standalone); | |||
| // Checks if should display install popup notification: | |||
| @@ -2,7 +2,7 @@ | |||
| // This is because caching would make development more difficult (changes would not | |||
| // be reflected on the first load after each change). | |||
| const staticCacheName = 'site-static-v-0-9-9'; // IMPORTANT: CHANGE THE VERSION IN THIS NAME EVERY TIME THE APP IS DEPLOYED ON SERVER WITH CHANGES!!! | |||
| const staticCacheName = 'site-static-v-0-9-14'; // IMPORTANT: CHANGE THE VERSION IN THIS NAME EVERY TIME THE APP IS DEPLOYED ON SERVER WITH CHANGES!!! | |||
| const appsettings_url = 'appsettings.json'; | |||
| const assets = [ | |||
| './', | |||
| @@ -24,7 +24,7 @@ const assets = [ | |||
| '/doneimage', | |||
| '/failureimage', | |||
| '/warningimage', | |||
| 'favicon.ico', | |||
| '/favicon.ico', | |||
| 'images/batch_found.png', | |||
| 'images/batch_fundvelo.png', | |||
| 'images/batch_kulturlegi.png', | |||
| @@ -107,7 +107,8 @@ function fromNetwork(request, timeout) { | |||
| clearTimeout(timeoutId); | |||
| var responseClone = response.clone(); | |||
| caches.open(staticCacheName).then(function (cache) { | |||
| cache.put(request, responseClone); | |||
| if (request.method != 'POST') // post can't be cached, causes an exception | |||
| cache.put(request, responseClone); | |||
| }); | |||
| fulfill(response); | |||
| }, reject); | |||