From 28ac2bf4727d9452b3c144967486a12ca9b48b9b Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 3 Dec 2016 00:37:45 +0100 Subject: [PATCH 1/3] Renders the background color property --- BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs b/BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs index e5680ea7..9480e863 100644 --- a/BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs +++ b/BookAStar/BookAStar.Droid/Markdown/MarkdownViewRenderer.cs @@ -55,10 +55,14 @@ namespace BookAStar.Droid { // Subscribe editorTemplate.Model = new Markdown.MarkdownViewModel - { Content = e.NewElement.Markdown, Editable = e.NewElement.Editable }; + { + Content = e.NewElement.Markdown, Editable = e.NewElement.Editable + }; var html = editorTemplate.GenerateString(); EditorView.LoadDataWithBaseURL("file:///android_asset/", html, "text/html", "utf-8", null); + EditorView.SetBackgroundColor(e.NewElement.BackgroundColor.ToAndroid()); + } } From 7917f9db81b587841c31a99fec14b7daed88aa4a Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 3 Dec 2016 00:38:26 +0100 Subject: [PATCH 2/3] more strings --- BookAStar/BookAStar/Strings.resx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/BookAStar/BookAStar/Strings.resx b/BookAStar/BookAStar/Strings.resx index 8d5461a7..c4b023af 100644 --- a/BookAStar/BookAStar/Strings.resx +++ b/BookAStar/BookAStar/Strings.resx @@ -117,9 +117,15 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Annuler la validation + Faire un devis + + Valider le devis sans signer + Editer le devis @@ -137,6 +143,12 @@ Étoile montante + + Signer + + + Signer le devis? + Incontournable @@ -144,6 +156,6 @@ À ne manquer sous aucun prétexte - Voir le devis + Voir les devis validés \ No newline at end of file From 5e180158d33e44d7a28da985604082e7e255b063 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 5 Dec 2016 05:51:24 +0100 Subject: [PATCH 3/3] =?UTF-8?q?une=20signature=20cot=C3=A9=20serveur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Markdown/MarkdownEditor.cs | 2 +- .../Markdown/MarkdownViewModel.cs | 2 + BookAStar/BookAStar/App.xaml.cs | 2 + .../Behaviors/EditorMaxLengthValidator.cs | 42 +++++++++ .../Behaviors/EmailValidatorBehavior.cs | 31 +------ .../Behaviors/MarkdownViewLengthValidator.Cs | 39 ++++++++ .../BookAStar/Behaviors/MaxLengthValidator.cs | 63 ------------- .../Behaviors/RegexValidatorBehavior.cs | 53 +++++++++++ BookAStar/BookAStar/BookAStar.csproj | 24 ++++- .../BookAStar/Data/ApiCallFailedException.cs | 21 +++++ BookAStar/BookAStar/Data/DataManager.cs | 4 +- BookAStar/BookAStar/Data/EstimateEntity.cs | 62 +++++++++++++ BookAStar/BookAStar/Data/LocalState.cs | 16 ---- .../BookAStar/Data/NonCrUD/RemoteFiles.cs | 7 -- BookAStar/BookAStar/Data/RemoteEntity.cs | 31 ++++--- .../BookAStar/Model/Workflow/Estimate.cs | 9 +- BookAStar/BookAStar/Pages/DocSigning.xaml | 2 +- BookAStar/BookAStar/Pages/DocSigning.xaml.cs | 4 +- .../EstimatePages/EditBillingLinePage.xaml | 4 +- .../Pages/EstimatePages/EditEstimatePage.xaml | 8 +- .../EstimatePages/EditEstimatePage.xaml.cs | 58 ++++++------ .../EstimatePages/EstimateSigningPage.xaml | 80 ++++++++++++++++ .../EstimatePages/EstimateSigningPage.xaml.cs | 84 +++++++++++++++++ .../Pages/EstimatePages/ViewEstimatePage.xaml | 3 - .../Pages/UserProfile/UserProfilePage.xaml.cs | 28 +++++- BookAStar/BookAStar/Strings.Designer.cs | 92 ++++++++++++++++++- BookAStar/BookAStar/Strings.resx | 18 ++++ .../BookAStar/ViewModels/EditingViewModel.cs | 37 +++++++- .../BillingLineViewModel.cs | 30 ++++-- .../EditEstimateViewModel.cs | 16 +++- .../ViewModels/Signing/DocSigningViewModel.cs | 17 ---- .../Signing/EstimateSigningViewModel.cs | 15 +++ BookAStar/BookAStar/Views/MarkdownView.cs | 5 +- 33 files changed, 698 insertions(+), 211 deletions(-) create mode 100644 BookAStar/BookAStar/Behaviors/EditorMaxLengthValidator.cs create mode 100644 BookAStar/BookAStar/Behaviors/MarkdownViewLengthValidator.Cs delete mode 100644 BookAStar/BookAStar/Behaviors/MaxLengthValidator.cs create mode 100644 BookAStar/BookAStar/Behaviors/RegexValidatorBehavior.cs create mode 100644 BookAStar/BookAStar/Data/ApiCallFailedException.cs create mode 100644 BookAStar/BookAStar/Data/EstimateEntity.cs delete mode 100644 BookAStar/BookAStar/Data/LocalState.cs create mode 100644 BookAStar/BookAStar/Pages/EstimatePages/EstimateSigningPage.xaml create mode 100644 BookAStar/BookAStar/Pages/EstimatePages/EstimateSigningPage.xaml.cs delete mode 100644 BookAStar/BookAStar/ViewModels/Signing/DocSigningViewModel.cs create mode 100644 BookAStar/BookAStar/ViewModels/Signing/EstimateSigningViewModel.cs diff --git a/BookAStar/BookAStar.Droid/Markdown/MarkdownEditor.cs b/BookAStar/BookAStar.Droid/Markdown/MarkdownEditor.cs index 63160726..f6dea44a 100644 --- a/BookAStar/BookAStar.Droid/Markdown/MarkdownEditor.cs +++ b/BookAStar/BookAStar.Droid/Markdown/MarkdownEditor.cs @@ -17,7 +17,7 @@ using System.Linq; using System.Text; -[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorTemplatePreprocessor", "4.2.0.703")] +[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorTemplatePreprocessor", "4.2.1.62")] public partial class MarkdownEditor : MarkdownEditorBase { diff --git a/BookAStar/BookAStar.Droid/Markdown/MarkdownViewModel.cs b/BookAStar/BookAStar.Droid/Markdown/MarkdownViewModel.cs index ef482e8e..5a310f0b 100644 --- a/BookAStar/BookAStar.Droid/Markdown/MarkdownViewModel.cs +++ b/BookAStar/BookAStar.Droid/Markdown/MarkdownViewModel.cs @@ -9,6 +9,7 @@ using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; +using Android.Graphics; namespace BookAStar.Droid.Markdown { @@ -17,6 +18,7 @@ namespace BookAStar.Droid.Markdown protected static MarkdownDeep.Markdown markdown = new MarkdownDeep.Markdown(); public string Content { get; set; } public bool Editable { get; set; } + public string GetHtml() { return markdown.Transform(Content); diff --git a/BookAStar/BookAStar/App.xaml.cs b/BookAStar/BookAStar/App.xaml.cs index c90b1eef..a909593a 100644 --- a/BookAStar/BookAStar/App.xaml.cs +++ b/BookAStar/BookAStar/App.xaml.cs @@ -27,6 +27,7 @@ namespace BookAStar using ViewModels.UserProfile; using Pages.UserProfile; using ViewModels.EstimateAndBilling; + using Pages.EstimatePages; public partial class App : Application // superclass new in 1.3 { @@ -150,6 +151,7 @@ namespace BookAStar ViewFactory.Register(); ViewFactory.Register(); ViewFactory.Register(); + ViewFactory.Register(); ConfigManager = new GenericConfigSettingsMgr(s => MainSettings.AppSettings.GetValueOrDefault(s, MainSettings.SettingsDefault), null); } diff --git a/BookAStar/BookAStar/Behaviors/EditorMaxLengthValidator.cs b/BookAStar/BookAStar/Behaviors/EditorMaxLengthValidator.cs new file mode 100644 index 00000000..d712eb27 --- /dev/null +++ b/BookAStar/BookAStar/Behaviors/EditorMaxLengthValidator.cs @@ -0,0 +1,42 @@ +using System; +using Xamarin.Forms; + +namespace BookAStar.Behaviors +{ + public class EditorMaxLengthValidator : Behavior + { + public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create("MaxLength", typeof(int), typeof(EditorMaxLengthValidator), 0); + public static readonly BindableProperty MinLengthProperty = BindableProperty.Create("MinLength", typeof(int), typeof(EditorMaxLengthValidator), 0); + + public int MaxLength + { + get { return (int)GetValue(MaxLengthProperty); } + set { SetValue(MaxLengthProperty, value); } + } + public int MinLength + { + get { return (int)GetValue(MinLengthProperty); } + set { SetValue(MinLengthProperty, value); } + } + + protected override void OnAttachedTo(Editor bindable) + { + bindable.TextChanged += bindable_TextChanged; + } + + public bool IsValid { get; set; } + + private void bindable_TextChanged(object sender, TextChangedEventArgs e) + { + IsValid = e.NewTextValue == null? false : ( e.NewTextValue.Length >= MinLength && e.NewTextValue.Length <= MaxLength ) ; + if (!IsValid) if (e.NewTextValue!=null) if (e.NewTextValue.Length > MaxLength) + ((Editor)sender).Text = e.NewTextValue.Substring(0, MaxLength); + } + + protected override void OnDetachingFrom(Editor bindable) + { + bindable.TextChanged -= bindable_TextChanged; + } + } + +} diff --git a/BookAStar/BookAStar/Behaviors/EmailValidatorBehavior.cs b/BookAStar/BookAStar/Behaviors/EmailValidatorBehavior.cs index 78371a4a..76765708 100644 --- a/BookAStar/BookAStar/Behaviors/EmailValidatorBehavior.cs +++ b/BookAStar/BookAStar/Behaviors/EmailValidatorBehavior.cs @@ -8,39 +8,14 @@ using Xamarin.Forms; namespace BookAStar.Behaviors { - public class EmailValidatorBehavior : Behavior + public class EmailValidatorBehavior : RegexValidatorBehavior { const string emailRegex = @"^(?("")("".+?(? + { + public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create("MaxLength", typeof(int), typeof(MarkdownViewLengthValidator), 0); + public static readonly BindableProperty MinLengthProperty = BindableProperty.Create("MinLength", typeof(int), typeof(MarkdownViewLengthValidator), 0); + public int MaxLength + { + get { return (int)GetValue(MaxLengthProperty); } + set { SetValue(MaxLengthProperty, value); } + } + public int MinLength + { + get { return (int)GetValue(MinLengthProperty); } + set { SetValue(MinLengthProperty, value); } + } + protected override void OnAttachedTo(MarkdownView bindable) + { + bindable.Modified += bindable_TextChanged; + } + + public bool IsValid { get; set; } + + private void bindable_TextChanged(object sender, TextChangedEventArgs e) + { + IsValid = e.NewTextValue == null ? false : (e.NewTextValue.Length >= MinLength && e.NewTextValue.Length <= MaxLength); + if (!IsValid) if (e.NewTextValue != null) if (e.NewTextValue.Length > MaxLength) + ((Editor)sender).Text = e.NewTextValue.Substring(0, MaxLength); + } + + protected override void OnDetachingFrom(MarkdownView bindable) + { + bindable.Modified -= bindable_TextChanged; + } + } +} diff --git a/BookAStar/BookAStar/Behaviors/MaxLengthValidator.cs b/BookAStar/BookAStar/Behaviors/MaxLengthValidator.cs deleted file mode 100644 index b70f5896..00000000 --- a/BookAStar/BookAStar/Behaviors/MaxLengthValidator.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Xamarin.Forms; - -namespace BookAStar.Behaviors -{ - public class EditorMaxLengthValidator : Behavior - { - public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create("MaxLength", typeof(int), typeof(MaxLengthValidator), 0); - - public int MaxLength - { - get { return (int)GetValue(MaxLengthProperty); } - set { SetValue(MaxLengthProperty, value); } - } - - protected override void OnAttachedTo(Editor bindable) - { - bindable.TextChanged += bindable_TextChanged; - } - - public bool IsValid { get; set; } - - private void bindable_TextChanged(object sender, TextChangedEventArgs e) - { - IsValid = e.NewTextValue == null? false : ( e.NewTextValue.Length > 0 && e.NewTextValue.Length <= MaxLength ) ; - if (!IsValid) if (e.NewTextValue!=null) if (e.NewTextValue.Length > MaxLength) - ((Editor)sender).Text = e.NewTextValue.Substring(0, MaxLength); - } - - protected override void OnDetachingFrom(Editor bindable) - { - bindable.TextChanged -= bindable_TextChanged; - } - } - public class MaxLengthValidator : Behavior - { - public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create("MaxLength", typeof(int), typeof(MaxLengthValidator), 0); - - public int MaxLength - { - get { return (int)GetValue(MaxLengthProperty); } - set { SetValue(MaxLengthProperty, value); } - } - - protected override void OnAttachedTo(Entry bindable) - { - bindable.TextChanged += bindable_TextChanged; - } - - private void bindable_TextChanged(object sender, TextChangedEventArgs e) - { - //if (MaxLength != null && MaxLength.HasValue) - if (e.NewTextValue.Length > MaxLength) - ((Entry)sender).Text = e.NewTextValue.Substring(0, MaxLength); - } - - protected override void OnDetachingFrom(Entry bindable) - { - bindable.TextChanged -= bindable_TextChanged; - - } - - } -} diff --git a/BookAStar/BookAStar/Behaviors/RegexValidatorBehavior.cs b/BookAStar/BookAStar/Behaviors/RegexValidatorBehavior.cs new file mode 100644 index 00000000..9b06ec05 --- /dev/null +++ b/BookAStar/BookAStar/Behaviors/RegexValidatorBehavior.cs @@ -0,0 +1,53 @@ +using System; +using System.Text.RegularExpressions; +using Xamarin.Forms; + +namespace BookAStar.Behaviors +{ + public class RegexValidatorBehavior : Behavior + { + private string regexp = @"^([\d\w]+)$"; + // Creating BindableProperties with Limited write access: http://iosapi.xamarin.com/index.aspx?link=M%3AXamarin.Forms.BindableObject.SetValue(Xamarin.Forms.BindablePropertyKey%2CSystem.Object) + + static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(RegexValidatorBehavior), false); + + public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty; + + public bool IsValid + { + get { return (bool)base.GetValue(IsValidProperty); } + private set { base.SetValue(IsValidPropertyKey, value); } + } + + protected string Regexp + { + get + { + return regexp; + } + + set + { + regexp = value; + } + } + + protected override void OnAttachedTo(Entry bindable) + { + bindable.TextChanged += HandleTextChanged; + } + + + void HandleTextChanged(object sender, TextChangedEventArgs e) + { + IsValid = (Regex.IsMatch(e.NewTextValue, regexp, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250))); + ((Entry)sender).TextColor = IsValid ? Color.Default : Color.Red; + } + + protected override void OnDetachingFrom(Entry bindable) + { + bindable.TextChanged -= HandleTextChanged; + + } + } +} diff --git a/BookAStar/BookAStar/BookAStar.csproj b/BookAStar/BookAStar/BookAStar.csproj index 86ee64c2..8aa906b8 100644 --- a/BookAStar/BookAStar/BookAStar.csproj +++ b/BookAStar/BookAStar/BookAStar.csproj @@ -44,14 +44,17 @@ - + + + - + + @@ -59,6 +62,9 @@ + + EstimateSigningPage.xaml + EstimatesClientPage.xaml @@ -89,7 +95,7 @@ DocSigning.xaml - + @@ -272,6 +278,12 @@ ..\..\packages\Xam.Plugin.Connectivity.2.2.12\lib\MonoAndroid10\Plugin.Connectivity.Abstractions.dll + + ..\..\packages\Xam.Plugin.Media.2.3.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Plugin.Media.dll + + + ..\..\packages\Xam.Plugin.Media.2.3.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Plugin.Media.Abstractions.dll + ..\..\packages\Xam.Plugins.Settings.2.5.1.0\lib\portable-net45+wp80+win8+wpa81\Plugin.Settings.dll True @@ -478,6 +490,12 @@ Designer + + + MSBuild:UpdateDesignTimeXaml + Designer + + diff --git a/BookAStar/BookAStar/Data/ApiCallFailedException.cs b/BookAStar/BookAStar/Data/ApiCallFailedException.cs new file mode 100644 index 00000000..aca74183 --- /dev/null +++ b/BookAStar/BookAStar/Data/ApiCallFailedException.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BookAStar.Data +{ + class ApiCallFailedException : Exception + { + public ApiCallFailedException(string message) : base(message) + { + + } + + public ApiCallFailedException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/BookAStar/BookAStar/Data/DataManager.cs b/BookAStar/BookAStar/Data/DataManager.cs index 84e08776..68d076f4 100644 --- a/BookAStar/BookAStar/Data/DataManager.cs +++ b/BookAStar/BookAStar/Data/DataManager.cs @@ -13,7 +13,7 @@ { // TODO estimatetemplate rating service product tag public RemoteEntityRO BookQueries { get; set; } - public RemoteEntity Estimates { get; set; } + public EstimateEntity Estimates { get; set; } public RemoteEntity Blogspot { get; set; } internal RemoteFilesEntity RemoteFiles { get; set; } @@ -41,7 +41,7 @@ public DataManager() { BookQueries = new RemoteEntityRO("bookquery", q => q.Id); - Estimates = new RemoteEntity("estimate", x => x.Id); + Estimates = new EstimateEntity(); Blogspot = new RemoteEntity("blog", x=>x.Id); Contacts = new LocalEntity(c => c.UserId); diff --git a/BookAStar/BookAStar/Data/EstimateEntity.cs b/BookAStar/BookAStar/Data/EstimateEntity.cs new file mode 100644 index 00000000..6504478c --- /dev/null +++ b/BookAStar/BookAStar/Data/EstimateEntity.cs @@ -0,0 +1,62 @@ + +namespace BookAStar.Data +{ + using Helpers; + using Model.Workflow; + using Newtonsoft.Json; + using System; + using System.Diagnostics; + using System.IO; + using System.Net.Http; + + public class EstimateEntity : RemoteEntity + { + public EstimateEntity() : base("estimate", e => e.Id) + { + } + + public async void SignAsProvider(Estimate estimate, Stream pngStream) + { + + if (estimate.Id == 0) + { + var ok = await this.Create(estimate); + if (!ok) + { + await App.DisplayAlert("Erreur d'accès au serveur", "Echec de l'envoi de l'estimation"); + return; + } + this.Add(estimate); + } + using (HttpClient client = UserHelpers.CreateClient()) + { + try + { + var requestContent = new MultipartFormDataContent(); + var content = new StreamContent(pngStream); + var filename = $"prosign-{estimate.Id}.png"; + content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); + content.Headers.Add("Content-Disposition", $"form-data; name=\"file\"; filename=\"{filename}\""); + requestContent.Add(content, "file", filename); + using (var response = await client.PostAsync( + Constants.YavscApiUrl + $"/pdfestimate/prosign/{estimate.Id}", requestContent)) + { + if (!response.IsSuccessStatusCode) + { + var errContent = await response.Content.ReadAsStringAsync(); + throw new ApiCallFailedException($"SignAsProvider: {response.StatusCode} / {errContent}"); + } + var json = await response.Content.ReadAsStringAsync(); + JsonConvert.PopulateObject(json, estimate); + } + } + catch (Exception ex) + { + Debug.WriteLine(ex.ToString()); + } + } + this.SaveEntity(); + } + + } +} diff --git a/BookAStar/BookAStar/Data/LocalState.cs b/BookAStar/BookAStar/Data/LocalState.cs deleted file mode 100644 index bdb82ae7..00000000 --- a/BookAStar/BookAStar/Data/LocalState.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BookAStar.Data -{ - public enum LocalState - { - UpToDate = 0, - New, - Edited, - Removed - } -} diff --git a/BookAStar/BookAStar/Data/NonCrUD/RemoteFiles.cs b/BookAStar/BookAStar/Data/NonCrUD/RemoteFiles.cs index aa7e6eaa..be0fe1db 100644 --- a/BookAStar/BookAStar/Data/NonCrUD/RemoteFiles.cs +++ b/BookAStar/BookAStar/Data/NonCrUD/RemoteFiles.cs @@ -6,13 +6,6 @@ namespace BookAStar.Data.NonCrUD { using Helpers; using Model.FileSystem; - using System.Linq; - /* - public class DirectoryEntryChangingEvent : EventArgs - { - public UserDirectoryInfo OldItem { get; set; } - public UserDirectoryInfo NewItem { get; set; } - }*/ public class RemoteFilesEntity : RemoteEntity { diff --git a/BookAStar/BookAStar/Data/RemoteEntity.cs b/BookAStar/BookAStar/Data/RemoteEntity.cs index 3a4b8b62..edc962df 100644 --- a/BookAStar/BookAStar/Data/RemoteEntity.cs +++ b/BookAStar/BookAStar/Data/RemoteEntity.cs @@ -22,7 +22,7 @@ namespace BookAStar.Data public bool CanExecute(object parameter) { - return !IsExecuting && (MainSettings.CurrentUser != null); + return !IsExecuting; } public RemoteEntity(string controllerName, Func getKey) : base(getKey) @@ -36,7 +36,7 @@ namespace BookAStar.Data protected void BeforeExecute() { if (IsExecuting) - throw new InvalidOperationException("Already executing"); + throw new InvalidOperationException(Strings.AlreadyExecuting); IsExecuting = true; if (CanExecuteChanged != null) CanExecuteChanged.Invoke(this, new EventArgs()); @@ -71,7 +71,7 @@ namespace BookAStar.Data } catch (WebException webex) { - throw new ServiceNotAvailable("No remote entity", webex); + throw new ServiceNotAvailable(Strings.ENoRemoteEntity, webex); } } @@ -123,23 +123,27 @@ namespace BookAStar.Data return item; } - public virtual async void Create(V item) + public virtual async Task Create(V item) { + bool created = false; BeforeExecute(); using (HttpClient client = UserHelpers.CreateClient()) { var stringContent = JsonConvert.SerializeObject(item); + HttpContent content = new StringContent( stringContent, Encoding.UTF8, "application/json" ); using (var response = await client.PostAsync(ControllerUri, content)) { - if (!response.IsSuccessStatusCode) + created = response.IsSuccessStatusCode; + if (!created) { // TODO throw custom exception, and catch to inform user var errcontent = await response.Content.ReadAsStringAsync(); - Debug.WriteLine($"Create failed posting {stringContent} @ {ControllerUri.AbsoluteUri}: {errcontent}"); + Debug.WriteLine(string.Format(Strings.CreationFailed)); + Debug.WriteLine(errcontent); } else { @@ -148,14 +152,15 @@ namespace BookAStar.Data JsonConvert.PopulateObject(recontent, item); } } - } CurrentItem = item; AfterExecuting(); + return created; } - public virtual async void Update(V item) + public virtual async Task Update(V item) { + var updated = false; BeforeExecute(); var uri = GetUri(GetKey(item)); @@ -166,13 +171,16 @@ namespace BookAStar.Data ); using (var response = await client.PutAsync(uri, content)) { - if (!response.IsSuccessStatusCode) + updated = response.IsSuccessStatusCode; + if (!updated) {// TODO throw custom exception, and catch to inform user if (response.StatusCode == HttpStatusCode.BadRequest) { - var recontent = await response.Content.ReadAsStringAsync(); + var errorcontent = await response.Content.ReadAsStringAsync(); + Debug.WriteLine(string.Format(Strings.UpdateFailed)); + Debug.WriteLine(errorcontent); + } - else Debug.WriteLine($"Update failed ({item} @ {uri.AbsolutePath} )"); } @@ -188,6 +196,7 @@ namespace BookAStar.Data CurrentItem = item; AfterExecuting(); + return updated; } public virtual async void Delete(K key) diff --git a/BookAStar/BookAStar/Model/Workflow/Estimate.cs b/BookAStar/BookAStar/Model/Workflow/Estimate.cs index 586c8185..2640e744 100644 --- a/BookAStar/BookAStar/Model/Workflow/Estimate.cs +++ b/BookAStar/BookAStar/Model/Workflow/Estimate.cs @@ -77,9 +77,14 @@ namespace BookAStar.Model.Workflow return Bill?.Aggregate((decimal)0, (t, l) => t + l.Count * l.UnitaryCost) ?? (decimal)0; } } - - public DateTime LatestValidationDate { get; set; } + /// + /// This validation comes from the provider. + /// As long as it's an estimate, no client validation + /// is formaly needed + /// + public DateTime ProviderValidationDate { get; set; } public DateTime ClientApprouvalDate { get; set; } + } } diff --git a/BookAStar/BookAStar/Pages/DocSigning.xaml b/BookAStar/BookAStar/Pages/DocSigning.xaml index fe1dec3e..284d5707 100644 --- a/BookAStar/BookAStar/Pages/DocSigning.xaml +++ b/BookAStar/BookAStar/Pages/DocSigning.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:signature="clr-namespace:SignaturePad.Forms;assembly=SignaturePad.Forms" xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar" - x:Class="BookAStar.ViewModels.Signing.DocSigning"> + x:Class="BookAStar.ViewModels.Signing.Signing"> - + - + diff --git a/BookAStar/BookAStar/Pages/EstimatePages/EditEstimatePage.xaml b/BookAStar/BookAStar/Pages/EstimatePages/EditEstimatePage.xaml index 4dbb56b3..955ef2e7 100644 --- a/BookAStar/BookAStar/Pages/EstimatePages/EditEstimatePage.xaml +++ b/BookAStar/BookAStar/Pages/EstimatePages/EditEstimatePage.xaml @@ -4,6 +4,7 @@ x:Class="BookAStar.Pages.EditEstimatePage" xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar" xmlns:local="clr-namespace:BookAStar;assembly=BookAStar" + xmlns:behaviors="clr-namespace:BookAStar.Behaviors;assembly=BookAStar" Style="{StaticResource PageStyle}"> @@ -36,7 +37,12 @@ Editable="True" HorizontalOptions="FillAndExpand" Markdown="{Binding Description, Mode=TwoWay}" - VerticalOptions="Start" /> + VerticalOptions="Start" > + + + + + { - bill.Add(com); + bill.Add(new BillingLineViewModel(com)); DataManager.Current.EstimationCache.SaveEntity(); })}; - lineView.PropertyChanged += LineView_PropertyChanged; App.NavigationService.NavigateTo( true, lineView ); } protected void OnEditLine(object sender, ItemTappedEventArgs e) { - var line = (BillingLine)e.Item; - var bill = ((EditEstimateViewModel)BindingContext).Bill; - var lineView = new BillingLineViewModel(line) + var line = (BillingLineViewModel)e.Item; + line.ValidateCommand = new Command(() => { - ValidateCommand = new Command(() => { - DataManager.Current.EstimationCache.SaveEntity(); - }) - }; - lineView.PropertyChanged += LineView_PropertyChanged; + DataManager.Current.EstimationCache.SaveEntity(); + }); - lineView.PropertyChanged += LineView_PropertyChanged; App.NavigationService.NavigateTo( - true, lineView ); + true, line ); } - - private void LineView_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + protected async void OnEstimateValidated(object sender, EventArgs e) { - DataManager.Current.EstimationCache.SaveEntity(); - } - - protected void OnEstimateValidated(object sender, EventArgs e) - { - var evm = (EditEstimateViewModel)BindingContext; - if (evm.Data.Id == 0) + var thisPage = this; + var evm = (EditEstimateViewModel) BindingContext; + var cmd = new Command( async (validated) => { - DataManager.Current.Estimates.Create(evm.Data); - // we have to manually add this item in our local collection, - // since we could prefer to update the whole collection - // from server, or whatever other scenario - DataManager.Current.Estimates.Add(evm.Data); - } else + if (validated) { + DataManager.Current.EstimationCache.Remove(evm); + DataManager.Current.EstimationCache.SaveEntity(); + } + await thisPage.Navigation.PopAsync(); + }); + var response = await App.DisplayActionSheet(Strings.SignOrNot, Strings.DonotsignEstimate, Strings.CancelValidation, new string[] { Strings.Sign }); + if (response == Strings.Sign) { - DataManager.Current.Estimates.Update(evm.Data); + App.NavigationService.NavigateTo(true, + new EstimateSigningViewModel(evm.Data) { ValidationCommand = cmd }); } - DataManager.Current.Estimates.SaveEntity(); - DataManager.Current.EstimationCache.Remove(evm); - DataManager.Current.EstimationCache.SaveEntity(); - Navigation.PopAsync(); + else if (response == Strings.CancelValidation) + return; + else cmd.Execute(true); + } } } diff --git a/BookAStar/BookAStar/Pages/EstimatePages/EstimateSigningPage.xaml b/BookAStar/BookAStar/Pages/EstimatePages/EstimateSigningPage.xaml new file mode 100644 index 00000000..65faecfb --- /dev/null +++ b/BookAStar/BookAStar/Pages/EstimatePages/EstimateSigningPage.xaml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +