une signature coté serveur
This commit is contained in:
parent
e22356f7ab
commit
7e7619db99
33 changed files with 698 additions and 211 deletions
|
|
@ -17,7 +17,7 @@ using System.Linq;
|
||||||
using System.Text;
|
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
|
public partial class MarkdownEditor : MarkdownEditorBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
|
using Android.Graphics;
|
||||||
|
|
||||||
namespace BookAStar.Droid.Markdown
|
namespace BookAStar.Droid.Markdown
|
||||||
{
|
{
|
||||||
|
|
@ -17,6 +18,7 @@ namespace BookAStar.Droid.Markdown
|
||||||
protected static MarkdownDeep.Markdown markdown = new MarkdownDeep.Markdown();
|
protected static MarkdownDeep.Markdown markdown = new MarkdownDeep.Markdown();
|
||||||
public string Content { get; set; }
|
public string Content { get; set; }
|
||||||
public bool Editable { get; set; }
|
public bool Editable { get; set; }
|
||||||
|
|
||||||
public string GetHtml()
|
public string GetHtml()
|
||||||
{
|
{
|
||||||
return markdown.Transform(Content);
|
return markdown.Transform(Content);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ namespace BookAStar
|
||||||
using ViewModels.UserProfile;
|
using ViewModels.UserProfile;
|
||||||
using Pages.UserProfile;
|
using Pages.UserProfile;
|
||||||
using ViewModels.EstimateAndBilling;
|
using ViewModels.EstimateAndBilling;
|
||||||
|
using Pages.EstimatePages;
|
||||||
|
|
||||||
public partial class App : Application // superclass new in 1.3
|
public partial class App : Application // superclass new in 1.3
|
||||||
{
|
{
|
||||||
|
|
@ -150,6 +151,7 @@ namespace BookAStar
|
||||||
ViewFactory.Register<EditEstimatePage, EditEstimateViewModel>();
|
ViewFactory.Register<EditEstimatePage, EditEstimateViewModel>();
|
||||||
ViewFactory.Register<UserFiles, DirectoryInfoViewModel>();
|
ViewFactory.Register<UserFiles, DirectoryInfoViewModel>();
|
||||||
ViewFactory.Register<UserProfilePage, UserProfileViewModel>();
|
ViewFactory.Register<UserProfilePage, UserProfileViewModel>();
|
||||||
|
ViewFactory.Register<EstimateSigningPage, EditEstimateViewModel>();
|
||||||
ConfigManager = new GenericConfigSettingsMgr(s =>
|
ConfigManager = new GenericConfigSettingsMgr(s =>
|
||||||
MainSettings.AppSettings.GetValueOrDefault<string>(s, MainSettings.SettingsDefault), null);
|
MainSettings.AppSettings.GetValueOrDefault<string>(s, MainSettings.SettingsDefault), null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
BookAStar/BookAStar/Behaviors/EditorMaxLengthValidator.cs
Normal file
42
BookAStar/BookAStar/Behaviors/EditorMaxLengthValidator.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace BookAStar.Behaviors
|
||||||
|
{
|
||||||
|
public class EditorMaxLengthValidator : Behavior<Editor>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -8,39 +8,14 @@ using Xamarin.Forms;
|
||||||
|
|
||||||
namespace BookAStar.Behaviors
|
namespace BookAStar.Behaviors
|
||||||
{
|
{
|
||||||
public class EmailValidatorBehavior : Behavior<Entry>
|
public class EmailValidatorBehavior : RegexValidatorBehavior
|
||||||
{
|
{
|
||||||
const string emailRegex = @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
|
const string emailRegex = @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
|
||||||
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$";
|
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$";
|
||||||
|
|
||||||
// Creating BindableProperties with Limited write access: http://iosapi.xamarin.com/index.aspx?link=M%3AXamarin.Forms.BindableObject.SetValue(Xamarin.Forms.BindablePropertyKey%2CSystem.Object)
|
public EmailValidatorBehavior()
|
||||||
|
|
||||||
static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(EmailValidatorBehavior), false);
|
|
||||||
|
|
||||||
public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;
|
|
||||||
|
|
||||||
public bool IsValid
|
|
||||||
{
|
{
|
||||||
get { return (bool)base.GetValue(IsValidProperty); }
|
Regexp = emailRegex;
|
||||||
private set { base.SetValue(IsValidPropertyKey, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAttachedTo(Entry bindable)
|
|
||||||
{
|
|
||||||
bindable.TextChanged += HandleTextChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void HandleTextChanged(object sender, TextChangedEventArgs e)
|
|
||||||
{
|
|
||||||
IsValid = (Regex.IsMatch(e.NewTextValue, emailRegex, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
|
|
||||||
((Entry)sender).TextColor = IsValid ? Color.Default : Color.Red;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDetachingFrom(Entry bindable)
|
|
||||||
{
|
|
||||||
bindable.TextChanged -= HandleTextChanged;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
BookAStar/BookAStar/Behaviors/MarkdownViewLengthValidator.Cs
Normal file
39
BookAStar/BookAStar/Behaviors/MarkdownViewLengthValidator.Cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using BookAStar.Views;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace BookAStar.Behaviors
|
||||||
|
{
|
||||||
|
public class MarkdownViewLengthValidator : Behavior<MarkdownView>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace BookAStar.Behaviors
|
|
||||||
{
|
|
||||||
public class EditorMaxLengthValidator : Behavior<Editor>
|
|
||||||
{
|
|
||||||
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<Entry>
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
53
BookAStar/BookAStar/Behaviors/RegexValidatorBehavior.cs
Normal file
53
BookAStar/BookAStar/Behaviors/RegexValidatorBehavior.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace BookAStar.Behaviors
|
||||||
|
{
|
||||||
|
public class RegexValidatorBehavior : Behavior<Entry>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,14 +44,17 @@
|
||||||
<Compile Include="Attributes\DisplayAttribute.cs" />
|
<Compile Include="Attributes\DisplayAttribute.cs" />
|
||||||
<Compile Include="Behaviors\EmailValidatorBehavior.cs" />
|
<Compile Include="Behaviors\EmailValidatorBehavior.cs" />
|
||||||
<Compile Include="Behaviors\IntegerEntryBehavior.cs" />
|
<Compile Include="Behaviors\IntegerEntryBehavior.cs" />
|
||||||
<Compile Include="Behaviors\MaxLengthValidator.cs" />
|
<Compile Include="Behaviors\EditorMaxLengthValidator.cs" />
|
||||||
<Compile Include="Behaviors\DecimalValidatorBehavior.cs" />
|
<Compile Include="Behaviors\DecimalValidatorBehavior.cs" />
|
||||||
|
<Compile Include="Behaviors\MarkdownViewLengthValidator.cs" />
|
||||||
<Compile Include="Behaviors\PickerBehavior.cs" />
|
<Compile Include="Behaviors\PickerBehavior.cs" />
|
||||||
|
<Compile Include="Behaviors\RegexValidatorBehavior.cs" />
|
||||||
<Compile Include="Behaviors\StarBehavior.cs" />
|
<Compile Include="Behaviors\StarBehavior.cs" />
|
||||||
<Compile Include="Constants.cs" />
|
<Compile Include="Constants.cs" />
|
||||||
<Compile Include="Converters\NotValueConverter.cs" />
|
<Compile Include="Converters\NotValueConverter.cs" />
|
||||||
<Compile Include="Converters\SignalRConnectionStateToObject.cs" />
|
<Compile Include="Converters\SignalRConnectionStateToObject.cs" />
|
||||||
<Compile Include="Data\LocalState.cs" />
|
<Compile Include="Data\ApiCallFailedException.cs" />
|
||||||
|
<Compile Include="Data\EstimateEntity.cs" />
|
||||||
<Compile Include="Data\NonCrUD\RemoteFiles.cs" />
|
<Compile Include="Data\NonCrUD\RemoteFiles.cs" />
|
||||||
<Compile Include="Model\FileSystem\UserDirectoryInfo.cs" />
|
<Compile Include="Model\FileSystem\UserDirectoryInfo.cs" />
|
||||||
<Compile Include="Model\FileSystem\UserFileInfo.cs" />
|
<Compile Include="Model\FileSystem\UserFileInfo.cs" />
|
||||||
|
|
@ -59,6 +62,9 @@
|
||||||
<Compile Include="Model\Social\Messaging\ChatStatus.cs" />
|
<Compile Include="Model\Social\Messaging\ChatStatus.cs" />
|
||||||
<Compile Include="Model\Social\Messaging\PrivateMessage.cs" />
|
<Compile Include="Model\Social\Messaging\PrivateMessage.cs" />
|
||||||
<Compile Include="Model\UI\PageState.cs" />
|
<Compile Include="Model\UI\PageState.cs" />
|
||||||
|
<Compile Include="Pages\EstimatePages\EstimateSigningPage.xaml.cs">
|
||||||
|
<DependentUpon>EstimateSigningPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Pages\EstimatePages\EstimatesClientPage.xaml.cs">
|
<Compile Include="Pages\EstimatePages\EstimatesClientPage.xaml.cs">
|
||||||
<DependentUpon>EstimatesClientPage.xaml</DependentUpon>
|
<DependentUpon>EstimatesClientPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -89,7 +95,7 @@
|
||||||
<Compile Include="Pages\DocSigning.xaml.cs">
|
<Compile Include="Pages\DocSigning.xaml.cs">
|
||||||
<DependentUpon>DocSigning.xaml</DependentUpon>
|
<DependentUpon>DocSigning.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="ViewModels\Signing\DocSigningViewModel.cs" />
|
<Compile Include="ViewModels\Signing\EstimateSigningViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Signing\SignaturePadConfigViewModel.cs" />
|
<Compile Include="ViewModels\Signing\SignaturePadConfigViewModel.cs" />
|
||||||
<Compile Include="ViewModels\UserProfile\UserProfileViewModel.cs" />
|
<Compile Include="ViewModels\UserProfile\UserProfileViewModel.cs" />
|
||||||
<Compile Include="ViewModels\UserProfile\DirectoryInfoViewModel.cs" />
|
<Compile Include="ViewModels\UserProfile\DirectoryInfoViewModel.cs" />
|
||||||
|
|
@ -272,6 +278,12 @@
|
||||||
<Reference Include="Plugin.Connectivity.Abstractions">
|
<Reference Include="Plugin.Connectivity.Abstractions">
|
||||||
<HintPath>..\..\packages\Xam.Plugin.Connectivity.2.2.12\lib\MonoAndroid10\Plugin.Connectivity.Abstractions.dll</HintPath>
|
<HintPath>..\..\packages\Xam.Plugin.Connectivity.2.2.12\lib\MonoAndroid10\Plugin.Connectivity.Abstractions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Plugin.Media">
|
||||||
|
<HintPath>..\..\packages\Xam.Plugin.Media.2.3.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Plugin.Media.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Plugin.Media.Abstractions">
|
||||||
|
<HintPath>..\..\packages\Xam.Plugin.Media.2.3.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Plugin.Media.Abstractions.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Plugin.Settings, Version=2.5.1.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Plugin.Settings, Version=2.5.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Xam.Plugins.Settings.2.5.1.0\lib\portable-net45+wp80+win8+wpa81\Plugin.Settings.dll</HintPath>
|
<HintPath>..\..\packages\Xam.Plugins.Settings.2.5.1.0\lib\portable-net45+wp80+win8+wpa81\Plugin.Settings.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
|
|
@ -478,6 +490,12 @@
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Pages\EstimatePages\EstimateSigningPage.xaml">
|
||||||
|
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||||
<Import Project="..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
|
<Import Project="..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
|
|
||||||
21
BookAStar/BookAStar/Data/ApiCallFailedException.cs
Normal file
21
BookAStar/BookAStar/Data/ApiCallFailedException.cs
Normal file
|
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
{
|
{
|
||||||
// TODO estimatetemplate rating service product tag
|
// TODO estimatetemplate rating service product tag
|
||||||
public RemoteEntityRO<BookQueryData, long> BookQueries { get; set; }
|
public RemoteEntityRO<BookQueryData, long> BookQueries { get; set; }
|
||||||
public RemoteEntity<Estimate, long> Estimates { get; set; }
|
public EstimateEntity Estimates { get; set; }
|
||||||
public RemoteEntity<Blog, long> Blogspot { get; set; }
|
public RemoteEntity<Blog, long> Blogspot { get; set; }
|
||||||
internal RemoteFilesEntity RemoteFiles { get; set; }
|
internal RemoteFilesEntity RemoteFiles { get; set; }
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
public DataManager()
|
public DataManager()
|
||||||
{
|
{
|
||||||
BookQueries = new RemoteEntityRO<BookQueryData, long>("bookquery", q => q.Id);
|
BookQueries = new RemoteEntityRO<BookQueryData, long>("bookquery", q => q.Id);
|
||||||
Estimates = new RemoteEntity<Estimate, long>("estimate", x => x.Id);
|
Estimates = new EstimateEntity();
|
||||||
Blogspot = new RemoteEntity<Blog, long>("blog", x=>x.Id);
|
Blogspot = new RemoteEntity<Blog, long>("blog", x=>x.Id);
|
||||||
|
|
||||||
Contacts = new LocalEntity<ClientProviderInfo, string>(c => c.UserId);
|
Contacts = new LocalEntity<ClientProviderInfo, string>(c => c.UserId);
|
||||||
|
|
|
||||||
62
BookAStar/BookAStar/Data/EstimateEntity.cs
Normal file
62
BookAStar/BookAStar/Data/EstimateEntity.cs
Normal file
|
|
@ -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<Estimate, long>
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,13 +6,6 @@ namespace BookAStar.Data.NonCrUD
|
||||||
{
|
{
|
||||||
using Helpers;
|
using Helpers;
|
||||||
using Model.FileSystem;
|
using Model.FileSystem;
|
||||||
using System.Linq;
|
|
||||||
/*
|
|
||||||
public class DirectoryEntryChangingEvent : EventArgs
|
|
||||||
{
|
|
||||||
public UserDirectoryInfo OldItem { get; set; }
|
|
||||||
public UserDirectoryInfo NewItem { get; set; }
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public class RemoteFilesEntity : RemoteEntity<UserDirectoryInfo, FileAddress>
|
public class RemoteFilesEntity : RemoteEntity<UserDirectoryInfo, FileAddress>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace BookAStar.Data
|
||||||
|
|
||||||
public bool CanExecute(object parameter)
|
public bool CanExecute(object parameter)
|
||||||
{
|
{
|
||||||
return !IsExecuting && (MainSettings.CurrentUser != null);
|
return !IsExecuting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteEntity(string controllerName, Func<V, K> getKey) : base(getKey)
|
public RemoteEntity(string controllerName, Func<V, K> getKey) : base(getKey)
|
||||||
|
|
@ -36,7 +36,7 @@ namespace BookAStar.Data
|
||||||
protected void BeforeExecute()
|
protected void BeforeExecute()
|
||||||
{
|
{
|
||||||
if (IsExecuting)
|
if (IsExecuting)
|
||||||
throw new InvalidOperationException("Already executing");
|
throw new InvalidOperationException(Strings.AlreadyExecuting);
|
||||||
IsExecuting = true;
|
IsExecuting = true;
|
||||||
if (CanExecuteChanged != null)
|
if (CanExecuteChanged != null)
|
||||||
CanExecuteChanged.Invoke(this, new EventArgs());
|
CanExecuteChanged.Invoke(this, new EventArgs());
|
||||||
|
|
@ -71,7 +71,7 @@ namespace BookAStar.Data
|
||||||
}
|
}
|
||||||
catch (WebException webex)
|
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;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async void Create(V item)
|
public virtual async Task<bool> Create(V item)
|
||||||
{
|
{
|
||||||
|
bool created = false;
|
||||||
BeforeExecute();
|
BeforeExecute();
|
||||||
|
|
||||||
using (HttpClient client = UserHelpers.CreateClient())
|
using (HttpClient client = UserHelpers.CreateClient())
|
||||||
{
|
{
|
||||||
var stringContent = JsonConvert.SerializeObject(item);
|
var stringContent = JsonConvert.SerializeObject(item);
|
||||||
|
|
||||||
HttpContent content = new StringContent(
|
HttpContent content = new StringContent(
|
||||||
stringContent, Encoding.UTF8, "application/json"
|
stringContent, Encoding.UTF8, "application/json"
|
||||||
);
|
);
|
||||||
using (var response = await client.PostAsync(ControllerUri, content))
|
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
|
// TODO throw custom exception, and catch to inform user
|
||||||
var errcontent = await response.Content.ReadAsStringAsync();
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -148,14 +152,15 @@ namespace BookAStar.Data
|
||||||
JsonConvert.PopulateObject(recontent, item);
|
JsonConvert.PopulateObject(recontent, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentItem = item;
|
CurrentItem = item;
|
||||||
AfterExecuting();
|
AfterExecuting();
|
||||||
|
return created;
|
||||||
}
|
}
|
||||||
public virtual async void Update(V item)
|
public virtual async Task<bool> Update(V item)
|
||||||
{
|
{
|
||||||
|
var updated = false;
|
||||||
BeforeExecute();
|
BeforeExecute();
|
||||||
|
|
||||||
var uri = GetUri(GetKey(item));
|
var uri = GetUri(GetKey(item));
|
||||||
|
|
@ -166,13 +171,16 @@ namespace BookAStar.Data
|
||||||
);
|
);
|
||||||
using (var response = await client.PutAsync(uri, content))
|
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
|
{// TODO throw custom exception, and catch to inform user
|
||||||
if (response.StatusCode == HttpStatusCode.BadRequest)
|
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} )");
|
else Debug.WriteLine($"Update failed ({item} @ {uri.AbsolutePath} )");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -188,6 +196,7 @@ namespace BookAStar.Data
|
||||||
|
|
||||||
CurrentItem = item;
|
CurrentItem = item;
|
||||||
AfterExecuting();
|
AfterExecuting();
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async void Delete(K key)
|
public virtual async void Delete(K key)
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,14 @@ namespace BookAStar.Model.Workflow
|
||||||
return Bill?.Aggregate((decimal)0, (t, l) => t + l.Count * l.UnitaryCost) ?? (decimal)0;
|
return Bill?.Aggregate((decimal)0, (t, l) => t + l.Count * l.UnitaryCost) ?? (decimal)0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
public DateTime LatestValidationDate { get; set; }
|
/// This validation comes from the provider.
|
||||||
|
/// As long as it's an estimate, no client validation
|
||||||
|
/// is formaly needed
|
||||||
|
/// </summary>
|
||||||
|
public DateTime ProviderValidationDate { get; set; }
|
||||||
|
|
||||||
public DateTime ClientApprouvalDate { get; set; }
|
public DateTime ClientApprouvalDate { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:signature="clr-namespace:SignaturePad.Forms;assembly=SignaturePad.Forms"
|
xmlns:signature="clr-namespace:SignaturePad.Forms;assembly=SignaturePad.Forms"
|
||||||
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
||||||
x:Class="BookAStar.ViewModels.Signing.DocSigning">
|
x:Class="BookAStar.ViewModels.Signing.Signing">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<views:MarkdownView x:Name="mdView"
|
<views:MarkdownView x:Name="mdView"
|
||||||
Editable="False"
|
Editable="False"
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ using Xamarin.Forms;
|
||||||
|
|
||||||
namespace BookAStar.ViewModels.Signing
|
namespace BookAStar.ViewModels.Signing
|
||||||
{
|
{
|
||||||
public partial class DocSigning : ContentPage
|
public partial class Signing : ContentPage
|
||||||
{
|
{
|
||||||
public DocSigning()
|
public Signing()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,9 @@
|
||||||
<Label Text="Description de la ligne de facture"
|
<Label Text="Description de la ligne de facture"
|
||||||
Style="{StaticResource InputLabelStyle}"></Label>
|
Style="{StaticResource InputLabelStyle}"></Label>
|
||||||
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand">
|
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand">
|
||||||
<Editor HorizontalOptions="FillAndExpand" Text="{Binding Description, Mode=TwoWay}">
|
<Editor HorizontalOptions="FillAndExpand" Text="{Binding Description, Mode=TwoWay}">
|
||||||
<Editor.Behaviors>
|
<Editor.Behaviors>
|
||||||
<behaviors:EditorMaxLengthValidator x:Name="descriptionValidator" MaxLength="512" />
|
<behaviors:EditorMaxLengthValidator x:Name="descriptionLenValidator" MaxLength="512" MinLength="3" />
|
||||||
</Editor.Behaviors>
|
</Editor.Behaviors>
|
||||||
</Editor>
|
</Editor>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
x:Class="BookAStar.Pages.EditEstimatePage"
|
x:Class="BookAStar.Pages.EditEstimatePage"
|
||||||
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
||||||
xmlns:local="clr-namespace:BookAStar;assembly=BookAStar"
|
xmlns:local="clr-namespace:BookAStar;assembly=BookAStar"
|
||||||
|
xmlns:behaviors="clr-namespace:BookAStar.Behaviors;assembly=BookAStar"
|
||||||
Style="{StaticResource PageStyle}">
|
Style="{StaticResource PageStyle}">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
|
@ -36,7 +37,12 @@
|
||||||
Editable="True"
|
Editable="True"
|
||||||
HorizontalOptions="FillAndExpand"
|
HorizontalOptions="FillAndExpand"
|
||||||
Markdown="{Binding Description, Mode=TwoWay}"
|
Markdown="{Binding Description, Mode=TwoWay}"
|
||||||
VerticalOptions="Start" />
|
VerticalOptions="Start" >
|
||||||
|
<views:MarkdownView.Behaviors>
|
||||||
|
<behaviors:MarkdownViewLengthValidator x:Name="descriptionLenValidator" MaxLength="512" MinLength="3" />
|
||||||
|
|
||||||
|
</views:MarkdownView.Behaviors>
|
||||||
|
</views:MarkdownView>
|
||||||
<StackLayout x:Name="biAnVaLayout">
|
<StackLayout x:Name="biAnVaLayout">
|
||||||
<ListView x:Name="BillListView" ItemsSource="{Binding Bill}"
|
<ListView x:Name="BillListView" ItemsSource="{Binding Bill}"
|
||||||
MinimumHeightRequest="40" HasUnevenRows="true" VerticalOptions="FillAndExpand"
|
MinimumHeightRequest="40" HasUnevenRows="true" VerticalOptions="FillAndExpand"
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ using Xamarin.Forms;
|
||||||
namespace BookAStar.Pages
|
namespace BookAStar.Pages
|
||||||
{
|
{
|
||||||
using Data;
|
using Data;
|
||||||
|
using EstimatePages;
|
||||||
using Model.Workflow;
|
using Model.Workflow;
|
||||||
using ViewModels.EstimateAndBilling;
|
using ViewModels.EstimateAndBilling;
|
||||||
|
using ViewModels.Signing;
|
||||||
|
|
||||||
public partial class EditEstimatePage : ContentPage
|
public partial class EditEstimatePage : ContentPage
|
||||||
{
|
{
|
||||||
|
|
@ -46,54 +48,46 @@ namespace BookAStar.Pages
|
||||||
var bill = ((EditEstimateViewModel)BindingContext).Bill;
|
var bill = ((EditEstimateViewModel)BindingContext).Bill;
|
||||||
var lineView = new BillingLineViewModel(com)
|
var lineView = new BillingLineViewModel(com)
|
||||||
{ ValidateCommand = new Command(() => {
|
{ ValidateCommand = new Command(() => {
|
||||||
bill.Add(com);
|
bill.Add(new BillingLineViewModel(com));
|
||||||
DataManager.Current.EstimationCache.SaveEntity();
|
DataManager.Current.EstimationCache.SaveEntity();
|
||||||
})};
|
})};
|
||||||
lineView.PropertyChanged += LineView_PropertyChanged;
|
|
||||||
App.NavigationService.NavigateTo<EditBillingLinePage>(
|
App.NavigationService.NavigateTo<EditBillingLinePage>(
|
||||||
true, lineView );
|
true, lineView );
|
||||||
}
|
}
|
||||||
protected void OnEditLine(object sender, ItemTappedEventArgs e)
|
protected void OnEditLine(object sender, ItemTappedEventArgs e)
|
||||||
{
|
{
|
||||||
var line = (BillingLine)e.Item;
|
var line = (BillingLineViewModel)e.Item;
|
||||||
var bill = ((EditEstimateViewModel)BindingContext).Bill;
|
line.ValidateCommand = new Command(() =>
|
||||||
var lineView = new BillingLineViewModel(line)
|
|
||||||
{
|
{
|
||||||
ValidateCommand = new Command(() => {
|
DataManager.Current.EstimationCache.SaveEntity();
|
||||||
DataManager.Current.EstimationCache.SaveEntity();
|
});
|
||||||
})
|
|
||||||
};
|
|
||||||
lineView.PropertyChanged += LineView_PropertyChanged;
|
|
||||||
|
|
||||||
lineView.PropertyChanged += LineView_PropertyChanged;
|
|
||||||
App.NavigationService.NavigateTo<EditBillingLinePage>(
|
App.NavigationService.NavigateTo<EditBillingLinePage>(
|
||||||
true, lineView );
|
true, line );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async void OnEstimateValidated(object sender, EventArgs e)
|
||||||
private void LineView_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
DataManager.Current.EstimationCache.SaveEntity();
|
var thisPage = this;
|
||||||
}
|
var evm = (EditEstimateViewModel) BindingContext;
|
||||||
|
var cmd = new Command<bool>( async (validated) =>
|
||||||
protected void OnEstimateValidated(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var evm = (EditEstimateViewModel)BindingContext;
|
|
||||||
if (evm.Data.Id == 0)
|
|
||||||
{
|
{
|
||||||
DataManager.Current.Estimates.Create(evm.Data);
|
if (validated) {
|
||||||
// we have to manually add this item in our local collection,
|
DataManager.Current.EstimationCache.Remove(evm);
|
||||||
// since we could prefer to update the whole collection
|
DataManager.Current.EstimationCache.SaveEntity();
|
||||||
// from server, or whatever other scenario
|
}
|
||||||
DataManager.Current.Estimates.Add(evm.Data);
|
await thisPage.Navigation.PopAsync();
|
||||||
} else
|
});
|
||||||
|
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<EstimateSigningPage>(true,
|
||||||
|
new EstimateSigningViewModel(evm.Data) { ValidationCommand = cmd });
|
||||||
}
|
}
|
||||||
DataManager.Current.Estimates.SaveEntity();
|
else if (response == Strings.CancelValidation)
|
||||||
DataManager.Current.EstimationCache.Remove(evm);
|
return;
|
||||||
DataManager.Current.EstimationCache.SaveEntity();
|
else cmd.Execute(true);
|
||||||
Navigation.PopAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
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.Pages.EstimatePages.EstimateSigningPage">
|
||||||
|
|
||||||
|
|
||||||
|
<ContentPage.Content>
|
||||||
|
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
|
||||||
|
<ScrollView>
|
||||||
|
<StackLayout>
|
||||||
|
<Grid MinimumHeightRequest="12">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="2*" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Client.UserName}" ></Label>
|
||||||
|
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Query.Location.Address}" ></Label>
|
||||||
|
<Label Grid.Row="0" Grid.Column="2" Text="{Binding Query.EventDate, StringFormat='{0:dddd d MMMM yyyy à hh:mm}'}" ></Label>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Label Text="{Binding Title}" />
|
||||||
|
|
||||||
|
<views:MarkdownView x:Name="mdview"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
Markdown="{Binding Description}"
|
||||||
|
/>
|
||||||
|
<ListView x:Name="billListView" ItemsSource="{Binding Bill}"
|
||||||
|
MinimumHeightRequest="40" HasUnevenRows="true" VerticalOptions="FillAndExpand"
|
||||||
|
HeightRequest="40" >
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate >
|
||||||
|
<ViewCell>
|
||||||
|
<ViewCell.View>
|
||||||
|
<Grid MinimumHeightRequest="12">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="30" />
|
||||||
|
<ColumnDefinition Width="90" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Text="{Binding Description}"
|
||||||
|
Grid.Row="0" Grid.Column="0" ></Label>
|
||||||
|
<Label Text="{Binding Duration, StringFormat=\{0\}}"
|
||||||
|
Grid.Row="0" Grid.Column="1" ></Label>
|
||||||
|
<Label Text="{Binding Count}"
|
||||||
|
Grid.Row="0" Grid.Column="2" ></Label>
|
||||||
|
<Label Text="{Binding UnitaryCost}"
|
||||||
|
Grid.Row="0" Grid.Column="3"
|
||||||
|
FontFamily="Monospace"></Label>
|
||||||
|
</Grid>
|
||||||
|
</ViewCell.View>
|
||||||
|
</ViewCell>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
<Label FormattedText="{Binding FormattedTotal}"/>
|
||||||
|
</StackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
<signature:SignaturePadView x:Name="padView"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
BackgroundColor="White"
|
||||||
|
CaptionText="Caption This" CaptionTextColor="Black"
|
||||||
|
ClearText="Clear Me!" ClearTextColor="Red"
|
||||||
|
PromptText="Prompt Here" PromptTextColor="Red"
|
||||||
|
SignatureLineColor="Aqua" StrokeColor="Black" StrokeWidth="2" />
|
||||||
|
<Button Clicked="OnValidate" Text="Valider cette signature" x:Name="btnValidate" />
|
||||||
|
|
||||||
|
</StackLayout>
|
||||||
|
</ContentPage.Content>
|
||||||
|
</ContentPage>
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
using SignaturePad.Forms;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace BookAStar.Pages.EstimatePages
|
||||||
|
{
|
||||||
|
using Data;
|
||||||
|
using ViewModels.EstimateAndBilling;
|
||||||
|
using ViewModels.Signing;
|
||||||
|
|
||||||
|
public partial class EstimateSigningPage : ContentPage
|
||||||
|
{
|
||||||
|
|
||||||
|
public EstimateSigningPage(EstimateSigningViewModel model)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
BindingContext = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnValidate (object sender, EventArgs ev)
|
||||||
|
{
|
||||||
|
btnValidate.IsEnabled = false;
|
||||||
|
if (DataManager.Current.Estimates.IsExecuting)
|
||||||
|
{
|
||||||
|
await App.DisplayAlert(Strings.OperationPending, Strings.oups);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var evm = (EditEstimateViewModel)BindingContext;
|
||||||
|
var estimate = evm.Data;
|
||||||
|
var pngStream = await padView.GetImageStreamAsync(SignatureImageFormat.Png);
|
||||||
|
pngStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
DataManager.Current.Estimates.SignAsProvider(estimate, pngStream);
|
||||||
|
DataManager.Current.Estimates.SaveEntity();
|
||||||
|
await Navigation.PopAsync();
|
||||||
|
|
||||||
|
var ParentValidationCommand = ((EstimateSigningViewModel)BindingContext).ValidationCommand;
|
||||||
|
if (ParentValidationCommand != null)
|
||||||
|
ParentValidationCommand.Execute(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnGetStats(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var points = padView.Points.ToArray();
|
||||||
|
using (var image = await padView.GetImageStreamAsync(SignatureImageFormat.Png))
|
||||||
|
{
|
||||||
|
var pointCount = points.Count();
|
||||||
|
var imageSize = image.Length / 1000;
|
||||||
|
var linesCount = points.Count(p => p == Point.Zero) + (points.Length > 0 ? 1 : 0);
|
||||||
|
await DisplayAlert("Stats", $"The signature has {linesCount} lines or {pointCount} points, and is {imageSize:#,###.0}KB (in memory) when saved as a PNG.", "Cool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async void OnChangeTheme(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var action = await DisplayActionSheet("Change Theme", "Cancel", null, "White", "Black", "Aqua");
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case "White":
|
||||||
|
padView.BackgroundColor = Color.White;
|
||||||
|
padView.StrokeColor = Color.Black;
|
||||||
|
padView.ClearTextColor = Color.Black;
|
||||||
|
padView.ClearText = "Clear Markers";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Black":
|
||||||
|
padView.BackgroundColor = Color.Black;
|
||||||
|
padView.StrokeColor = Color.White;
|
||||||
|
padView.ClearTextColor = Color.White;
|
||||||
|
padView.ClearText = "Clear Chalk";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Aqua":
|
||||||
|
padView.BackgroundColor = Color.Aqua;
|
||||||
|
padView.StrokeColor = Color.Red;
|
||||||
|
padView.ClearTextColor = Color.Black;
|
||||||
|
padView.ClearText = "Clear The Aqua";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,9 +33,6 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Label Text="{Binding Title}" />
|
<Label Text="{Binding Title}" />
|
||||||
|
|
||||||
<Label Text="{Binding Description}" />
|
|
||||||
|
|
||||||
<views:MarkdownView x:Name="mdview"
|
<views:MarkdownView x:Name="mdview"
|
||||||
HorizontalOptions="FillAndExpand"
|
HorizontalOptions="FillAndExpand"
|
||||||
Markdown="{Binding Description}"
|
Markdown="{Binding Description}"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
using BookAStar.ViewModels.UserProfile;
|
using BookAStar.ViewModels.UserProfile;
|
||||||
|
using Plugin.Media;
|
||||||
|
using Plugin.Media.Abstractions;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
@ -14,9 +16,31 @@ namespace BookAStar.Pages.UserProfile
|
||||||
AvatarButton.Clicked += AvatarButton_Clicked;
|
AvatarButton.Clicked += AvatarButton_Clicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AvatarButton_Clicked (object sender, EventArgs e)
|
private async void AvatarButton_Clicked (object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
|
||||||
|
{
|
||||||
|
DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
|
||||||
|
{
|
||||||
|
Directory = "Sample",
|
||||||
|
Name = "test.jpg"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (file == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await DisplayAlert("File Location", file.Path, "OK");
|
||||||
|
AvatarButton.Image.File = file.Path;
|
||||||
|
/* ImageSource.FromStream(() =>
|
||||||
|
{
|
||||||
|
var stream = file.GetStream();
|
||||||
|
file.Dispose();
|
||||||
|
return stream;
|
||||||
|
}); */
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnManageFiles(object sender, EventArgs e)
|
public void OnManageFiles(object sender, EventArgs e)
|
||||||
|
|
|
||||||
92
BookAStar/BookAStar/Strings.Designer.cs
generated
92
BookAStar/BookAStar/Strings.Designer.cs
generated
|
|
@ -61,6 +61,33 @@ namespace BookAStar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Une execution est déjà en cours.
|
||||||
|
/// </summary>
|
||||||
|
public static string AlreadyExecuting {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AlreadyExecuting", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Annuler la validation.
|
||||||
|
/// </summary>
|
||||||
|
public static string CancelValidation {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CancelValidation", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à La création a échoué, contenu envoyé: {stringContent} @ Uri: {ControllerUri.AbsoluteUri}: Erreur : {errcontent}.
|
||||||
|
/// </summary>
|
||||||
|
public static string CreationFailed {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CreationFailed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recherche une chaîne localisée semblable à Faire un devis.
|
/// Recherche une chaîne localisée semblable à Faire un devis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -70,6 +97,15 @@ namespace BookAStar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Valider le devis sans signer.
|
||||||
|
/// </summary>
|
||||||
|
public static string DonotsignEstimate {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DonotsignEstimate", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recherche une chaîne localisée semblable à Editer le devis.
|
/// Recherche une chaîne localisée semblable à Editer le devis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -79,6 +115,15 @@ namespace BookAStar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Erreur d'accès aux données distantes.
|
||||||
|
/// </summary>
|
||||||
|
public static string ENoRemoteEntity {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ENoRemoteEntity", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recherche une chaîne localisée semblable à Star.
|
/// Recherche une chaîne localisée semblable à Star.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -115,6 +160,42 @@ namespace BookAStar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Opération en cours.
|
||||||
|
/// </summary>
|
||||||
|
public static string OperationPending {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("OperationPending", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à oups..
|
||||||
|
/// </summary>
|
||||||
|
public static string oups {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("oups", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Signer.
|
||||||
|
/// </summary>
|
||||||
|
public static string Sign {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Sign", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Signer le devis?.
|
||||||
|
/// </summary>
|
||||||
|
public static string SignOrNot {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SignOrNot", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recherche une chaîne localisée semblable à Incontournable.
|
/// Recherche une chaîne localisée semblable à Incontournable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -134,7 +215,16 @@ namespace BookAStar {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recherche une chaîne localisée semblable à Voir le devis.
|
/// Recherche une chaîne localisée semblable à La mise à jour a échoué..
|
||||||
|
/// </summary>
|
||||||
|
public static string UpdateFailed {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("UpdateFailed", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recherche une chaîne localisée semblable à Voir les devis validés.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ViewEstimate {
|
public static string ViewEstimate {
|
||||||
get {
|
get {
|
||||||
|
|
|
||||||
|
|
@ -117,9 +117,15 @@
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="AlreadyExecuting" xml:space="preserve">
|
||||||
|
<value>Une execution est déjà en cours</value>
|
||||||
|
</data>
|
||||||
<data name="CancelValidation" xml:space="preserve">
|
<data name="CancelValidation" xml:space="preserve">
|
||||||
<value>Annuler la validation</value>
|
<value>Annuler la validation</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CreationFailed" xml:space="preserve">
|
||||||
|
<value>La création a échoué, contenu envoyé: {stringContent} @ Uri: {ControllerUri.AbsoluteUri}: Erreur : {errcontent}</value>
|
||||||
|
</data>
|
||||||
<data name="DoEstimate" xml:space="preserve">
|
<data name="DoEstimate" xml:space="preserve">
|
||||||
<value>Faire un devis</value>
|
<value>Faire un devis</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -129,6 +135,9 @@
|
||||||
<data name="EditEstimate" xml:space="preserve">
|
<data name="EditEstimate" xml:space="preserve">
|
||||||
<value>Editer le devis</value>
|
<value>Editer le devis</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ENoRemoteEntity" xml:space="preserve">
|
||||||
|
<value>Erreur d'accès aux données distantes</value>
|
||||||
|
</data>
|
||||||
<data name="FiveStars" xml:space="preserve">
|
<data name="FiveStars" xml:space="preserve">
|
||||||
<value>Star</value>
|
<value>Star</value>
|
||||||
<comment>Da star, da one</comment>
|
<comment>Da star, da one</comment>
|
||||||
|
|
@ -143,6 +152,12 @@
|
||||||
<data name="OneStar" xml:space="preserve">
|
<data name="OneStar" xml:space="preserve">
|
||||||
<value>Étoile montante</value>
|
<value>Étoile montante</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="OperationPending" xml:space="preserve">
|
||||||
|
<value>Opération en cours</value>
|
||||||
|
</data>
|
||||||
|
<data name="oups" xml:space="preserve">
|
||||||
|
<value>oups.</value>
|
||||||
|
</data>
|
||||||
<data name="Sign" xml:space="preserve">
|
<data name="Sign" xml:space="preserve">
|
||||||
<value>Signer</value>
|
<value>Signer</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -158,4 +173,7 @@
|
||||||
<data name="ViewEstimate" xml:space="preserve">
|
<data name="ViewEstimate" xml:space="preserve">
|
||||||
<value>Voir les devis validés</value>
|
<value>Voir les devis validés</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="UpdateFailed" xml:space="preserve">
|
||||||
|
<value>La mise à jour a échoué.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -14,15 +14,42 @@ namespace BookAStar.ViewModels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EditingViewModel: ViewModel
|
public class EditingViewModel: ViewModel
|
||||||
{
|
{
|
||||||
private LocalState state;
|
bool existsRemotely;
|
||||||
public LocalState State {
|
public bool ExistsRemotely
|
||||||
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return state;
|
return existsRemotely;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
base.SetProperty<LocalState>(ref state, value);
|
base.SetProperty<bool>(ref existsRemotely, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid;
|
||||||
|
public bool IsValid
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.SetProperty<bool>(ref isValid, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDirty;
|
||||||
|
public bool IsDirty
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return isDirty;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.SetProperty<bool>(ref isDirty, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
|
|
||||||
public BillingLineViewModel(BillingLine data)
|
public BillingLineViewModel(BillingLine data)
|
||||||
{
|
{
|
||||||
this.data = data ?? new BillingLine();
|
this.Data = data;
|
||||||
// sets durationValue & durationUnit
|
|
||||||
count = data.Count;
|
|
||||||
description = data.Description;
|
|
||||||
|
|
||||||
Duration = data.Duration;
|
|
||||||
unitaryCostText = data.UnitaryCost.ToString("G", CultureInfo.InvariantCulture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int count;
|
private int count;
|
||||||
|
|
@ -48,6 +42,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
{
|
{
|
||||||
SetProperty<string>(ref description, value);
|
SetProperty<string>(ref description, value);
|
||||||
data.Description = description;
|
data.Description = description;
|
||||||
|
IsValid = !string.IsNullOrWhiteSpace(description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decimal unitaryCost;
|
decimal unitaryCost;
|
||||||
|
|
@ -166,5 +161,26 @@ pour décrire la quantité de travail associée à ce type de service")]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BillingLine Data
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetProperty<BillingLine>(ref data, value);
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
// sets durationValue & durationUnit
|
||||||
|
count = data.Count;
|
||||||
|
description = data.Description;
|
||||||
|
|
||||||
|
Duration = data.Duration;
|
||||||
|
unitaryCostText = data.UnitaryCost.ToString("G", CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using BookAStar.Model;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using BookAStar.Data;
|
using BookAStar.Data;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace BookAStar.ViewModels.EstimateAndBilling
|
namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
{
|
{
|
||||||
|
|
@ -17,6 +18,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Builds a new view model on estimate,
|
/// Builds a new view model on estimate,
|
||||||
/// sets <c>Data</c> with given value parameter
|
/// sets <c>Data</c> with given value parameter
|
||||||
|
|
@ -28,12 +30,18 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void Bill_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
private void Bill_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
Data.Bill = new List<BillingLine>( Bill );
|
Data.Bill = Bill.Select(l => l.Data).ToList();
|
||||||
NotifyPropertyChanged("FormattedTotal");
|
NotifyPropertyChanged("FormattedTotal");
|
||||||
NotifyPropertyChanged("Bill");
|
NotifyPropertyChanged("Bill");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Estimate data;
|
private Estimate data;
|
||||||
public Estimate Data { get { return data; } set {
|
public Estimate Data { get { return data; } set {
|
||||||
SetProperty<Estimate>(ref data, value);
|
SetProperty<Estimate>(ref data, value);
|
||||||
|
|
@ -42,7 +50,9 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
if (data.Bill == null) data.Bill = new List<BillingLine>();
|
if (data.Bill == null) data.Bill = new List<BillingLine>();
|
||||||
AttachedFiles = new ObservableCollection<string>(data.AttachedFiles);
|
AttachedFiles = new ObservableCollection<string>(data.AttachedFiles);
|
||||||
AttachedGraphicList = new ObservableCollection<string>(data.AttachedGraphics);
|
AttachedGraphicList = new ObservableCollection<string>(data.AttachedGraphics);
|
||||||
Bill = new ObservableCollection<BillingLine>(data.Bill);
|
Bill = new ObservableCollection<BillingLineViewModel>(data.Bill.Select(
|
||||||
|
l => new BillingLineViewModel(l)
|
||||||
|
));
|
||||||
Bill.CollectionChanged += Bill_CollectionChanged;
|
Bill.CollectionChanged += Bill_CollectionChanged;
|
||||||
Title = Data.Title;
|
Title = Data.Title;
|
||||||
Description = Data.Description;
|
Description = Data.Description;
|
||||||
|
|
@ -64,7 +74,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public ObservableCollection<BillingLine> Bill
|
public ObservableCollection<BillingLineViewModel> Bill
|
||||||
{
|
{
|
||||||
get; protected set;
|
get; protected set;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using XLabs.Forms.Mvvm;
|
|
||||||
|
|
||||||
namespace BookAStar.ViewModels.Signing
|
|
||||||
{
|
|
||||||
class DocSigningViewModel: ViewModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The doc to sign, in Markdown format
|
|
||||||
/// </summary>
|
|
||||||
public string Document { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using BookAStar.Model.Workflow;
|
||||||
|
using BookAStar.ViewModels.EstimateAndBilling;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace BookAStar.ViewModels.Signing
|
||||||
|
{
|
||||||
|
public class EstimateSigningViewModel: EditEstimateViewModel
|
||||||
|
{
|
||||||
|
public EstimateSigningViewModel(Estimate document)
|
||||||
|
{
|
||||||
|
Data = document;
|
||||||
|
}
|
||||||
|
public Command<bool> ValidationCommand { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,13 +26,14 @@ namespace BookAStar.Views
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
var oldValue = Markdown;
|
||||||
if (Markdown != value)
|
if (Markdown != value)
|
||||||
{
|
{
|
||||||
SetValue(MarkdownProperty, value);
|
SetValue(MarkdownProperty, value);
|
||||||
|
|
||||||
if (Modified != null)
|
if (Modified != null)
|
||||||
{
|
{
|
||||||
Modified.Invoke(this, new EventArgs());
|
Modified.Invoke(this, new TextChangedEventArgs(oldValue, Markdown));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,7 +47,7 @@ namespace BookAStar.Views
|
||||||
set { SetValue (EditableProperty, value); }
|
set { SetValue (EditableProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<EventArgs> Modified;
|
public event EventHandler<TextChangedEventArgs> Modified;
|
||||||
|
|
||||||
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
|
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue