Merge branch 'vnext' of github.com:pazof/yavsc into vnext

vnext
Paul Schneider 8 years ago
commit 0bba44f1bb
28 changed files with 492 additions and 190 deletions

@ -9,7 +9,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookAStar.iOS", "BookAStar\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookAStar", "BookAStar\BookAStar\BookAStar.csproj", "{A0815650-0A0A-47B0-8826-771F0E1AD137}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yavsc.Client", "Yavsc.Client\Yavsc.Client.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YavscLib", "YavscLib\YavscLib.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

@ -387,9 +387,9 @@
</AndroidResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Yavsc.Client\Yavsc.Client.csproj">
<ProjectReference Include="..\..\YavscLib\YavscLib.csproj">
<Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
<Name>Yavsc.Client</Name>
<Name>YavscLib</Name>
</ProjectReference>
<ProjectReference Include="..\BookAStar\BookAStar.csproj">
<Project>{A0815650-0A0A-47B0-8826-771F0E1AD137}</Project>

@ -171,10 +171,6 @@
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Yavsc.Client\Yavsc.Client.csproj">
<Project>{67F9D3A8-F71E-4428-913F-C37AE82CDB24}</Project>
<Name>Yavsc.Client</Name>
</ProjectReference>
<ProjectReference Include="..\BookAStar\BookAStar.csproj">
<Project>{A0815650-0A0A-47B0-8826-771F0E1AD137}</Project>
<Name>BookAStar</Name>

@ -16,6 +16,8 @@
<Color x:Key="PageForegroundColor">#000000</Color>
<Color x:Key="TextColor">#000000</Color>
<Color x:Key="LabelColor">#000000</Color>
<Color x:Key="ErrorTextColor">#500000</Color>
<Color x:Key="HeadingTextColor">Black</Color>
<Color x:Key="NormalTextColor">Blue</Color>
<Color x:Key="GroupingTextColor">#5050ff</Color>
@ -43,9 +45,16 @@
<Setter Property="VerticalOptions" Value="Start" />
</Style>
<Style x:Key="ErrorLabelStyle" BasedOn="{StaticResource InputLabelStyle}" TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="TextColor" Value="{StaticResource ErrorTextColor}" />
</Style>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="TextColor" Value="{StaticResource LabelColor}" />
<Setter Property="LineBreakMode" Value="WordWrap" />
<Setter Property="HorizontalOptions" Value="FillAndExpand" />
</Style>
<Style x:Key="BigLabel" BasedOn="{StaticResource LabelStyle}" TargetType="Label">

@ -19,7 +19,6 @@ namespace BookAStar
using Data;
using Interfaces;
using Model;
using Model.UI;
using Pages;
using Plugin.Connectivity;
using Model.Social.Messaging;
@ -28,6 +27,7 @@ namespace BookAStar
using Pages.UserProfile;
using ViewModels.EstimateAndBilling;
using Pages.EstimatePages;
using ViewModels;
public partial class App : Application // superclass new in 1.3
{

@ -5,12 +5,17 @@ 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 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 static readonly BindableProperty IsValidProperty =
BindableProperty.Create("IsValid", typeof(bool), typeof(EditorMaxLengthValidator), false);
public static readonly BindableProperty ErrorProperty =
BindableProperty.Create("Error", typeof(string), typeof(EditorMaxLengthValidator), null);
public int MaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
get { return (int) GetValue(MaxLengthProperty); }
set { SetValue(MaxLengthProperty, value); }
}
public int MinLength
@ -24,13 +29,40 @@ namespace BookAStar.Behaviors
bindable.TextChanged += bindable_TextChanged;
}
public bool IsValid { get; set; }
public bool IsValid {
get { return (bool)GetValue(IsValidProperty); }
set { SetValue(IsValidProperty, value);
}
}
public string Error
{
get {
return (string)GetValue(ErrorProperty);
}
set
{
SetValue(ErrorProperty, value);
}
}
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);
if (e.NewTextValue != null && e.NewTextValue.Length >= MinLength)
{
if (e.NewTextValue.Length > MaxLength)
{
((Editor)sender).Text = e.NewTextValue.Substring(0, MaxLength);
Error = Strings.YourTextWasTooLong;
}
else Error = "";
IsValid = true;
}
else
{
Error = string.Format(Strings.MinMaxStringValidationError,
MinLength, MaxLength);
IsValid = false;
}
}
protected override void OnDetachingFrom(Editor bindable)

@ -6,7 +6,10 @@ namespace BookAStar.Behaviors
{
public static readonly BindableProperty MinProperty = BindableProperty.Create("Min", typeof(int), typeof(IntegerEntryBehavior), 0);
public static readonly BindableProperty MaxProperty = BindableProperty.Create("Max", typeof(int), typeof(IntegerEntryBehavior), 0);
public static readonly BindableProperty IsValidProperty =
BindableProperty.Create("IsValid", typeof(bool), typeof(IntegerEntryBehavior), false);
public static readonly BindableProperty ErrorProperty =
BindableProperty.Create("Error", typeof(string), typeof(IntegerEntryBehavior), null);
public int Min
{
get { return (int)GetValue(MinProperty); }
@ -30,8 +33,13 @@ namespace BookAStar.Behaviors
if (int.TryParse(e.NewTextValue, out val))
{
IsValid = (Min > Max) || (Max >= val && val >= Min);
Error = string.Format(Strings.MinMaxIntError, Min, Max);
}
else
{
IsValid = false;
Error = "";
}
else IsValid = false;
}
protected override void OnDetachingFrom(Entry bindable)
@ -39,6 +47,26 @@ namespace BookAStar.Behaviors
bindable.TextChanged -= bindable_TextChanged;
}
public bool IsValid { get; private set; }
public bool IsValid
{
get {
return (bool) GetValue(IsValidProperty);
}
set
{
SetValue(IsValidProperty, value);
}
}
public string Error
{
get
{
return (string) GetValue(ErrorProperty);
}
set
{
SetValue(ErrorProperty, value);
}
}
}
}

@ -61,7 +61,9 @@
<Compile Include="Model\Settings\SignatureSettings.cs" />
<Compile Include="Model\Social\Messaging\ChatStatus.cs" />
<Compile Include="Model\Social\Messaging\PrivateMessage.cs" />
<Compile Include="Model\UI\PageState.cs" />
<Compile Include="ViewModels\Validation\Error.cs" />
<Compile Include="ViewModels\Validation\ModelState.cs" />
<Compile Include="ViewModels\PageState.cs" />
<Compile Include="Pages\EstimatePages\EstimateSigningPage.xaml.cs">
<DependentUpon>EstimateSigningPage.xaml</DependentUpon>
</Compile>
@ -91,7 +93,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>Strings.en.resx</DependentUpon>
</Compile>
<Compile Include="ViewModels\EditingViewModel.cs" />
<Compile Include="ViewModels\Validation\EditingViewModel.cs" />
<Compile Include="Pages\DocSigning.xaml.cs">
<DependentUpon>DocSigning.xaml</DependentUpon>
</Compile>
@ -99,6 +101,7 @@
<Compile Include="ViewModels\Signing\SignaturePadConfigViewModel.cs" />
<Compile Include="ViewModels\UserProfile\UserProfileViewModel.cs" />
<Compile Include="ViewModels\UserProfile\DirectoryInfoViewModel.cs" />
<Compile Include="ViewModels\Validation\ErrorSeverity.cs" />
<Compile Include="Views\EnumPicker.cs" />
<Compile Include="Converters\BooleanToObjectConverter.cs" />
<Compile Include="Converters\EnumConverter.cs" />
@ -250,6 +253,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Model\Billing\" />
<Folder Include="Model\UI\" />
</ItemGroup>
<ItemGroup>
<Reference Include="ExifLib, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
@ -363,12 +367,6 @@
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Yavsc.Client\Yavsc.Client.csproj">
<Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
<Name>Yavsc.Client</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Pages\EstimatePages\EditEstimatePage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
@ -496,6 +494,12 @@
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\YavscLib\YavscLib.csproj">
<Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
<Name>YavscLib</Name>
</ProjectReference>
</ItemGroup>
<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')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

@ -3,11 +3,10 @@
using Model;
using Model.Blog;
using Model.Workflow;
using Model.UI;
using Model.Social.Messaging;
using Model.FileSystem;
using ViewModels.EstimateAndBilling;
using NonCrUD;
using ViewModels;
public class DataManager
{

@ -65,31 +65,25 @@ namespace BookAStar.Pages
if (editEstimateViewModel == null)
{
// First search for an existing estimate
var estimateToEdit = DataManager.Current.Estimates.FirstOrDefault(
estimate=> estimate.CommandId == bookQueryViewModel.Id
editEstimateViewModel = DataManager.Current.EstimationCache.FirstOrDefault(
estimate=> estimate.Query.Id == bookQueryViewModel.Id
);
if (estimateToEdit == null)
if (editEstimateViewModel == null)
{
DataManager.Current.Contacts.Merge(BookQuery.Client);
DataManager.Current.Contacts.SaveEntity();
estimateToEdit = new Estimate
editEstimateViewModel = new EditEstimateViewModel( new Estimate
{
ClientId = BookQuery.Client.UserId,
CommandId = BookQuery.Id,
OwnerId = MainSettings.CurrentUser.Id,
Id = 0
};
editEstimateViewModel = new EditEstimateViewModel(estimateToEdit);
});
DataManager.Current.EstimationCache.Add(editEstimateViewModel);
}
else
editEstimateViewModel = new EditEstimateViewModel(estimateToEdit);
DataManager.Current.EstimationCache.Add(editEstimateViewModel);
}
App.NavigationService.NavigateTo<EditEstimatePage>(true,
editEstimateViewModel);
}
private async void OnViewEstimate(object sender, EventArgs ev)

@ -44,12 +44,16 @@
<StackLayout x:Name="mainStackLayout">
<Label Text="Description de la ligne de facture"
Style="{StaticResource InputLabelStyle}"></Label>
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand">
<Editor HorizontalOptions="FillAndExpand" Text="{Binding Description, Mode=TwoWay}">
<Editor HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Text="{Binding Description, Mode=TwoWay}">
<Editor.Behaviors>
<behaviors:EditorMaxLengthValidator x:Name="descriptionLenValidator" MaxLength="512" MinLength="3" />
<behaviors:EditorMaxLengthValidator x:Name="descriptionLenValidator" MaxLength="12" MinLength="3" />
</Editor.Behaviors>
</Editor>
<StackLayout Orientation="Horizontal">
<Image x:Name="descriptionSuccessErrorImage"
Style="{Binding Source={x:Reference descriptionLenValidator}, Path=IsValid, Converter={StaticResource boolToStyleImage}}" />
<Label Text="{Binding Source={x:Reference descriptionLenValidator}, Path=Error}"
Style="{StaticResource ErrorLabelStyle}"></Label>
</StackLayout>
<Label Text="Durée de la prestation"
@ -74,18 +78,21 @@
</StackLayout>
<Label Text="Quantité facturée" Style="{StaticResource InputLabelStyle}"></Label>
<StackLayout Orientation="Horizontal">
<Entry Text="{Binding Count, Mode=TwoWay}" Placeholder="Quantité" Keyboard="Numeric"
Style="{StaticResource BigEntry}">
<Entry.Behaviors>
<behaviors:IntegerEntryBehavior x:Name="countValidator" Min="0" Max="10" />
</Entry.Behaviors>
</Entry>
<Image x:Name="countSuccessErrorImage"
<StackLayout Orientation="Horizontal">
<Image x:Name="countSuccessErrorImage"
Style="{Binding Source={x:Reference countValidator},
Path=IsValid,
Converter={StaticResource boolToStyleImage}}" />
</StackLayout>
<Label Text="{Binding Source={x:Reference countValidator}, Path=Error}"
Style="{StaticResource ErrorLabelStyle}"></Label>
</StackLayout>
<Label Text="Prix unitaire" Style="{StaticResource InputLabelStyle}"></Label>
<StackLayout Orientation="Horizontal">
@ -106,7 +113,7 @@
Command="{Binding ValidateCommand}"
Clicked="OnValidateClicked"></Button>
<Button Text="Supprimer"
Command="{Binding DeleteCommand}"
Command="{Binding RemoveCommand}"
Clicked="OnDeleteClicked"></Button>
</StackLayout>
</StackLayout>

@ -17,14 +17,17 @@ namespace BookAStar.Pages
picker.Items.Add(du);
BindingContext = model;
}
public void OnDeleteClicked(object sender, EventArgs e)
{
throw new NotImplementedException();
this.Navigation.PopAsync();
}
public void OnValidateClicked (object sender, EventArgs e)
{
this.Navigation.PopAsync();
}
protected override bool OnBackButtonPressed()
{
var bvm = (BillingLineViewModel)BindingContext;

@ -2,9 +2,11 @@
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BookAStar.Pages.EditEstimatePage"
xmlns:converters="clr-namespace:BookAStar.Converters;assembly=BookAStar"
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
xmlns:local="clr-namespace:BookAStar;assembly=BookAStar"
xmlns:behaviors="clr-namespace:BookAStar.Behaviors;assembly=BookAStar"
xmlns:extensions="clr-namespace:BookAStar.Extensions;assembly=BookAStar"
Style="{StaticResource PageStyle}">
<ContentPage.Resources>
<ResourceDictionary>
@ -14,14 +16,32 @@
<Style TargetType="Button">
<Setter Property="Style" Value="{StaticResource ButtonStyle}" />
</Style>
<converters:BooleanToObjectConverter x:Key="boolToStyleImage" x:TypeArguments="Style">
<converters:BooleanToObjectConverter.FalseObject>
<Style TargetType="Image">
<Setter Property="HeightRequest" Value="20" />
<Setter Property="Source"
Value="{extensions:ImageResource BookAStar.Images.Validation.error.png}" />
</Style>
</converters:BooleanToObjectConverter.FalseObject>
<converters:BooleanToObjectConverter.TrueObject>
<Style TargetType="Image">
<Setter Property="HeightRequest" Value="20" />
<Setter Property="Source"
Value="{extensions:ImageResource BookAStar.Images.Validation.success.png}" />
</Style>
</converters:BooleanToObjectConverter.TrueObject>
</converters:BooleanToObjectConverter>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<ScrollView>
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
<Grid MinimumHeightRequest="12">
<Grid HeightRequest="120">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
@ -35,9 +55,7 @@
<Entry Placeholder="Saisissez un titre pour ce devis" Text="{Binding Title, Mode=TwoWay}" />
<views:MarkdownView x:Name="mdview"
Editable="True"
HorizontalOptions="FillAndExpand"
Markdown="{Binding Description, Mode=TwoWay}"
VerticalOptions="Start" >
Markdown="{Binding Description, Mode=TwoWay}">
<views:MarkdownView.Behaviors>
<behaviors:MarkdownViewLengthValidator x:Name="descriptionLenValidator" MaxLength="512" MinLength="3" />
@ -45,13 +63,12 @@
</views:MarkdownView>
<StackLayout x:Name="biAnVaLayout">
<ListView x:Name="BillListView" ItemsSource="{Binding Bill}"
MinimumHeightRequest="40" HasUnevenRows="true" VerticalOptions="FillAndExpand"
HeightRequest="40" ItemTapped="OnEditLine">
HasUnevenRows="true" ItemTapped="OnEditLine">
<ListView.ItemTemplate>
<DataTemplate >
<ViewCell>
<ViewCell.View>
<Grid MinimumHeightRequest="12">
<ViewCell.View Padding="5,5,5,5" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
@ -60,6 +77,7 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="90" />
<ColumnDefinition Width="16" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Description}"
Grid.Row="0" Grid.Column="0" ></Label>
@ -70,6 +88,9 @@
<Label Text="{Binding UnitaryCost}"
Grid.Row="0" Grid.Column="3"
FontFamily="Monospace"></Label>
<Image Grid.Row="0" Grid.Column="4" Style="{Binding
Path=ViewModelState.IsValid,
Converter={StaticResource boolToStyleImage}}" ></Image>
</Grid>
</ViewCell.View>
</ViewCell>
@ -83,6 +104,5 @@
</StackLayout>
</StackLayout>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>

@ -57,11 +57,20 @@ namespace BookAStar.Pages
protected void OnEditLine(object sender, ItemTappedEventArgs e)
{
var line = (BillingLineViewModel)e.Item;
// update the validation command, that
// was creating a new line in the bill at creation time,
// now one only wants to update the line
line.ValidateCommand = new Command(() =>
{
DataManager.Current.EstimationCache.SaveEntity();
});
// and setup a removal command, that was not expected at creation time
var evm = (EditEstimateViewModel)BindingContext;
line.RemoveCommand = new Command(() =>
{
evm.Bill.Remove(line);
DataManager.Current.EstimationCache.SaveEntity();
});
App.NavigationService.NavigateTo<EditBillingLinePage>(
true, line );
}
@ -78,7 +87,9 @@ namespace BookAStar.Pages
}
await thisPage.Navigation.PopAsync();
});
var response = await App.DisplayActionSheet(Strings.SignOrNot, Strings.DonotsignEstimate, Strings.CancelValidation, new string[] { Strings.Sign });
var response = await App.DisplayActionSheet(
Strings.SignOrNot, Strings.DonotsignEstimate,
Strings.CancelValidation, new string[] { Strings.Sign });
if (response == Strings.Sign)
{
App.NavigationService.NavigateTo<EstimateSigningPage>(true,

@ -142,6 +142,42 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Valeur invalide.
/// </summary>
public static string InvalidValue {
get {
return ResourceManager.GetString("InvalidValue", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Veuillez saisir une valeur entre {0} et {1}..
/// </summary>
public static string MinMaxIntError {
get {
return ResourceManager.GetString("MinMaxIntError", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Veuillez saisir une description (entre {0} et {1} caractères)..
/// </summary>
public static string MinMaxStringValidationError {
get {
return ResourceManager.GetString("MinMaxStringValidationError", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Pas de description.
/// </summary>
public static string NoDescription {
get {
return ResourceManager.GetString("NoDescription", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Un artiste.
/// </summary>
@ -231,5 +267,14 @@ namespace BookAStar {
return ResourceManager.GetString("ViewEstimate", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Votre texte a été taillé car il était trop long..
/// </summary>
public static string YourTextWasTooLong {
get {
return ResourceManager.GetString("YourTextWasTooLong", resourceCulture);
}
}
}
}

@ -176,4 +176,19 @@
<data name="UpdateFailed" xml:space="preserve">
<value>La mise à jour a échoué.</value>
</data>
<data name="MinMaxStringValidationError" xml:space="preserve">
<value>Veuillez saisir une description (entre {0} et {1} caractères).</value>
</data>
<data name="YourTextWasTooLong" xml:space="preserve">
<value>Votre texte a été taillé car il était trop long.</value>
</data>
<data name="NoDescription" xml:space="preserve">
<value>Pas de description</value>
</data>
<data name="InvalidValue" xml:space="preserve">
<value>Valeur invalide</value>
</data>
<data name="MinMaxIntError" xml:space="preserve">
<value>Veuillez saisir une valeur entre {0} et {1}.</value>
</data>
</root>

@ -1,56 +0,0 @@
using BookAStar.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels
{
/// <summary>
/// Used to make the DataManager know how
/// to sync local and remote data
/// </summary>
public class EditingViewModel: ViewModel
{
bool existsRemotely;
public bool ExistsRemotely
{
get
{
return existsRemotely;
}
set
{
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);
}
}
}
}

@ -1,19 +1,54 @@
using BookAStar.Attributes;
using BookAStar.Interfaces;
using BookAStar.Model.Workflow;
using BookAStar.ViewModels.Validation;
using System;
using System.Globalization;
using System.Windows.Input;
using System.ComponentModel;
namespace BookAStar.ViewModels.EstimateAndBilling
{
public class BillingLineViewModel : EditingViewModel, IBillingLine
public class BillingLineViewModel : EditingViewModel<BillingLine>, IBillingLine
{
BillingLine data;
public ICommand RemoveCommand { get; set; }
public ICommand ValidateCommand { set; get; }
public BillingLineViewModel(BillingLine data)
public BillingLineViewModel(BillingLine data): base(data)
{
this.Data = data;
CheckCommand = new Action<BillingLine, ModelState>(
(l,s) => {
if (string.IsNullOrWhiteSpace(l.Description))
{
s.AddError("Description",Strings.NoDescription);
}
if (l.UnitaryCost < 0) { s.AddError("UnitaryCost", Strings.InvalidValue); }
if (l.Count < 0) { s.AddError("Count", Strings.InvalidValue); }
});
SyncData();
}
private void SyncData()
{
if (Data != null)
{
// set durationValue, durationUnit
Duration = Data.Duration;
// other redondant representation
count = Data.Count;
description = Data.Description;
unitaryCostText = Data.UnitaryCost.ToString("G", CultureInfo.InvariantCulture);
}
CheckCommand(Data, ViewModelState);
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.PropertyName=="Data")
{
SyncData();
}
}
private int count;
@ -27,7 +62,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
set
{
SetProperty<int>(ref count, value);
data.Count = count;
Data.Count = count;
}
}
private string description;
@ -41,10 +76,10 @@ namespace BookAStar.ViewModels.EstimateAndBilling
set
{
SetProperty<string>(ref description, value);
data.Description = description;
IsValid = !string.IsNullOrWhiteSpace(description);
Data.Description = description;
}
}
decimal unitaryCost;
public decimal UnitaryCost
{
@ -56,7 +91,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
set
{
SetProperty<decimal>(ref unitaryCost, value);
data.UnitaryCost = unitaryCost;
Data.UnitaryCost = unitaryCost;
}
}
@ -71,7 +106,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
set
{
SetProperty<int>(ref durationValue, value, "DurationValue");
data.Duration = this.Duration;
Data.Duration = this.Duration;
}
}
@ -94,7 +129,7 @@ pour décrire la quantité de travail associée à ce type de service")]
set
{
SetProperty<DurationUnits>(ref durationUnit, value, "DurationUnit");
data.Duration = this.Duration;
Data.Duration = this.Duration;
}
}
@ -120,7 +155,6 @@ pour décrire la quantité de travail associée à ce type de service")]
}
}
public ICommand ValidateCommand { set; get; }
public TimeSpan Duration
{
@ -161,26 +195,5 @@ 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);
}
}
}
}
}

@ -6,18 +6,13 @@ using Xamarin.Forms;
using BookAStar.Data;
using Newtonsoft.Json;
using System.Linq;
using BookAStar.ViewModels.Validation;
using System.ComponentModel;
namespace BookAStar.ViewModels.EstimateAndBilling
{
public class EditEstimateViewModel : EditingViewModel
public class EditEstimateViewModel : EditingViewModel<Estimate>
{
/// <summary>
/// For deserialization
/// </summary>
public EditEstimateViewModel()
{
}
/// <summary>
/// Builds a new view model on estimate,
@ -25,11 +20,37 @@ namespace BookAStar.ViewModels.EstimateAndBilling
/// </summary>
/// <param name="data"></param>
/// <param name="localState"></param>
public EditEstimateViewModel(Estimate data)
public EditEstimateViewModel(Estimate data) : base(data)
{
SyncData();
}
private void SyncData()
{
Data = data;
if (Data.AttachedFiles == null) Data.AttachedFiles = new List<string>();
if (Data.AttachedGraphics == null) Data.AttachedGraphics = new List<string>();
if (Data.Bill == null) Data.Bill = new List<BillingLine>();
AttachedFiles = new ObservableCollection<string>(Data.AttachedFiles);
AttachedGraphicList = new ObservableCollection<string>(Data.AttachedGraphics);
Bill = new ObservableCollection<BillingLineViewModel>(Data.Bill.Select(
l => new BillingLineViewModel(l)
));
Bill.CollectionChanged += Bill_CollectionChanged;
Title = Data.Title;
Description = Data.Description;
NotifyPropertyChanged("FormattedTotal");
NotifyPropertyChanged("Query");
NotifyPropertyChanged("CLient");
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.PropertyName == "Data")
{
SyncData();
}
}
/// <summary>
///
/// </summary>
@ -42,25 +63,6 @@ namespace BookAStar.ViewModels.EstimateAndBilling
NotifyPropertyChanged("Bill");
}
private Estimate data;
public Estimate Data { get { return data; } set {
SetProperty<Estimate>(ref data, value);
if (data.AttachedFiles == null) data.AttachedFiles = new List<string>();
if (data.AttachedGraphics == null) data.AttachedGraphics = new List<string>();
if (data.Bill == null) data.Bill = new List<BillingLine>();
AttachedFiles = new ObservableCollection<string>(data.AttachedFiles);
AttachedGraphicList = new ObservableCollection<string>(data.AttachedGraphics);
Bill = new ObservableCollection<BillingLineViewModel>(data.Bill.Select(
l => new BillingLineViewModel(l)
));
Bill.CollectionChanged += Bill_CollectionChanged;
Title = Data.Title;
Description = Data.Description;
NotifyPropertyChanged("FormattedTotal");
NotifyPropertyChanged("Query");
NotifyPropertyChanged("CLient");
} }
[JsonIgnore]
public ObservableCollection<string> AttachedFiles
{
@ -124,7 +126,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
{
get
{
OnPlatform<Font> lfs = (OnPlatform<Font>)App.Current.Resources["LargeFontSize"];
OnPlatform<Font> lfs = (OnPlatform<Font>)App.Current.Resources["MediumFontSize"];
OnPlatform<Color> etc = (OnPlatform<Color>)App.Current.Resources["EmphasisTextColor"];
return new FormattedString

@ -1,6 +1,6 @@
using XLabs.Forms.Mvvm;
namespace BookAStar.Model.UI
namespace BookAStar.ViewModels
{
internal class PageState
{

@ -6,9 +6,8 @@ namespace BookAStar.ViewModels.Signing
{
public class EstimateSigningViewModel: EditEstimateViewModel
{
public EstimateSigningViewModel(Estimate document)
public EstimateSigningViewModel(Estimate document): base(document)
{
Data = document;
}
public Command<bool> ValidationCommand { get; set; }
}

@ -0,0 +1,83 @@
using BookAStar.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using XLabs.Forms.Mvvm;
using System.ComponentModel;
namespace BookAStar.ViewModels.Validation
{
/// <summary>
/// Used to make the DataManager know how
/// to sync local and remote data
/// </summary>
public class EditingViewModel<DataType>: ViewModel
{
public Action<DataType, ModelState> CheckCommand { set; get; }
public DataType Data { get; set; }
private ModelState viewModelState = new ModelState();
public ModelState ViewModelState
{
get
{
return viewModelState;
}
set
{
base.SetProperty<ModelState>(ref viewModelState, value);
}
}
public EditingViewModel(DataType data)
{
this.Data = data;
ViewModelState = new ModelState();
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (CheckCommand != null)
{
ViewModelState.Clear();
CheckCommand(Data, ViewModelState);
}
}
/* NOTE : I had a dream.
bool existsRemotely;
public bool ExistsRemotely
{
get
{
return existsRemotely;
}
set
{
base.SetProperty<bool>(ref existsRemotely, value);
}
}
bool isDirty;
public bool IsDirty
{
get
{
return isDirty;
}
set
{
base.SetProperty<bool>(ref isDirty, value);
}
}
*/
}
}

@ -0,0 +1,13 @@
namespace BookAStar.ViewModels.Validation
{
public class InputError
{
public InputError(string errorMessage, ErrorSeverity severity)
{
Text = errorMessage;
Severity = severity;
}
public string Text { get; set; }
public ErrorSeverity Severity { get; set; }
}
}

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BookAStar.ViewModels.Validation
{
public enum ErrorSeverity
{
Crippling,
Bearable
}
}

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace BookAStar.ViewModels.Validation
{
public class ModelState : BindableObject
{
public static readonly BindableProperty IsValidProperty =
BindableProperty.Create("IsValid", typeof(bool), typeof(ModelState), false);
public static readonly BindableProperty ErrorsProperty =
BindableProperty.Create("Errors", typeof(Dictionary<string,List<InputError>>), typeof(ModelState), null);
public ModelState()
{
Errors = new Dictionary<string, List<InputError>>();
}
public bool IsValid
{
get
{
return (bool) GetValue(IsValidProperty);
}
}
public Dictionary<string, List<InputError>> Errors
{
get
{
return (Dictionary<string, List<InputError>>)GetValue(ErrorsProperty);
}
set
{
SetValue(ErrorsProperty, value);
}
}
public virtual void AddError(string propertyName, string errorMessage, ErrorSeverity severity = ErrorSeverity.Crippling)
{
InputError e = new InputError(errorMessage, severity) ;
if (Errors.ContainsKey(propertyName))
{
var errList = Errors[propertyName];
errList.Add(e);
}
else
{
Errors.Add(propertyName, new List<InputError>(new InputError [] { e }));
}
if (e.Severity < ErrorSeverity.Bearable)
SetValue(IsValidProperty, false);
}
public virtual void Clear ()
{
Errors.Clear();
SetValue(IsValidProperty, true);
}
}
}

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="EmitMSBuildWarning" BeforeTargets="Build">
<Warning Text="Les packages contenant des cibles et des fichiers de propriétés MSBuild ne peuvent pas être installés complètement dans des projets ciblant plusieurs infrastructures. Les cibles et les fichiers de propriétés MSBuild ont été ignorés." />
</Target>
</Project>

@ -14,6 +14,7 @@
},
"dependencies": {},
"frameworks": {
"net451": {}
"net451": {},
".NETPortable,Version=v4.5,Profile=Profile111": {}
}
}

@ -3,16 +3,14 @@
"version": 2,
"targets": {
".NETFramework,Version=v4.5.1": {},
".NETPortable,Version=v4.5,Profile=Profile111": {},
".NETFramework,Version=v4.5.1/debian.8-x86": {},
".NETFramework,Version=v4.5.1/debian.8-x64": {},
".NETPortable,Version=v4.5,Profile=Profile111/debian.8-x86": {},
".NETPortable,Version=v4.5,Profile=Profile111/debian.8-x64": {}
".NETPortable,Version=v4.5,Profile=Profile111": {}
},
"libraries": {},
"projectFileDependencyGroups": {
"": [],
".NETFramework,Version=v4.5.1": [],
".NETPortable,Version=v4.5,Profile=Profile111": []
}
},
"tools": {},
"projectFileToolGroups": {}
}
Loading…