changement de candidat à l'investissement

This commit is contained in:
Paul Schneider 2017-01-26 11:04:03 +01:00
commit be3087fff6
351 changed files with 359 additions and 497 deletions

View file

@ -0,0 +1,199 @@
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<BillingLine>, IBillingLine
{
public ICommand RemoveCommand { get; set; }
public ICommand ValidateCommand { set; get; }
public BillingLineViewModel(BillingLine data): base(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;
public int Count
{
get
{
return count;
}
set
{
SetProperty<int>(ref count, value);
Data.Count = count;
}
}
private string description;
public string Description
{
get
{
return description;
}
set
{
SetProperty<string>(ref description, value);
Data.Description = description;
}
}
decimal unitaryCost;
public decimal UnitaryCost
{
get
{
return unitaryCost;
}
set
{
SetProperty<decimal>(ref unitaryCost, value);
Data.UnitaryCost = unitaryCost;
}
}
protected int durationValue;
public int DurationValue
{
get
{
return durationValue;
}
set
{
SetProperty<int>(ref durationValue, value, "DurationValue");
Data.Duration = this.Duration;
}
}
public enum DurationUnits : int
{
Jours = 0,
Heures = 1,
Minutes = 2
}
private DurationUnits durationUnit;
[Display(Name = "Unité de temps", Description = @"Unité de temps utiliée
pour décrire la quantité de travail associée à ce type de service")]
public DurationUnits DurationUnit
{
get
{
return durationUnit;
}
set
{
SetProperty<DurationUnits>(ref durationUnit, value, "DurationUnit");
Data.Duration = this.Duration;
}
}
public static readonly string unitCostFormat = "0,.00";
string unitaryCostText;
public string UnitaryCostText
{
get
{
return unitaryCostText;
}
set
{
SetProperty<string>(ref unitaryCostText, value, "UnitaryCostText");
// TODO update behavior
decimal test;
if (decimal.TryParse(value, NumberStyles.Currency, CultureInfo.InvariantCulture, out test))
{
this.UnitaryCost = test;
}
}
}
public TimeSpan Duration
{
get
{
switch (DurationUnit)
{
case DurationUnits.Heures:
return new TimeSpan(DurationValue, 0, 0);
case DurationUnits.Jours:
return new TimeSpan(DurationValue * 24, 0, 0);
case DurationUnits.Minutes:
return new TimeSpan(0, DurationValue, 0);
// Assert(false); since all units are treated bellow
default:
return new TimeSpan(0, 0, DurationValue);
}
}
set
{
double days = value.TotalDays;
if (days >= 1.0)
{
DurationValue = (int)days;
DurationUnit = DurationUnits.Jours;
return;
}
double hours = value.TotalHours;
if (hours >= 1.0)
{
DurationValue = (int)hours;
DurationUnit = DurationUnits.Jours;
return;
}
DurationValue = (int)value.TotalMinutes;
DurationUnit = DurationUnits.Minutes;
}
}
}
}

View file

@ -0,0 +1,34 @@
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace BookAStar.ViewModels.EstimateAndBilling
{
using Data;
using Model;
using System.Linq;
public class BookQueriesViewModel : XLabs.Forms.Mvvm.ViewModel
{
public BookQueriesViewModel()
{
queries = new ObservableCollection<BookQueryViewModel>
(DataManager.Instance.BookQueries.Select(
q =>
new BookQueryViewModel(q)));
}
private ObservableCollection<BookQueryViewModel> queries;
public ObservableCollection<BookQueryViewModel> Queries
{
get
{
return queries;
}
}
public ICommand RefreshQueries
{
get; set;
}
}
}

View file

@ -0,0 +1,105 @@

using System;
using System.Diagnostics;
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.EstimateAndBilling
{
using Data;
using Helpers;
using Interfaces;
using Model;
using Model.Social;
using Model.Workflow;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
public class BookQueryViewModel : ViewModel, IBookQueryData
{
public BookQueryViewModel()
{
}
public BookQueryViewModel(BookQuery data)
{
Debug.Assert(data != null);
Client=data.Client;
Location = data.Location;
EventDate = data.EventDate;
Previsionnal = data.Previsionnal;
Id = data.Id;
estimates = new ObservableCollection<Estimate>(
DataManager.Instance.Estimates.Where(
e => e.Query.Id == Id
));
this.data = data;
}
private BookQuery data;
public BookQuery Data {
get
{
return data;
}
}
public ClientProviderInfo Client { get; set; }
public ImageSource Avatar
{
get
{
return UserHelpers.Avatar(Client.Avatar);
}
}
public ImageSource SmallAvatar
{
get
{
return UserHelpers.SmallAvatar(Client.Avatar, Client.UserName);
}
}
public Location Location { get; set; }
public long Id { get; set; }
public DateTime EventDate { get; set; }
public decimal? Previsionnal { get; set; }
public EditEstimateViewModel DraftEstimate
{
get
{
return DataManager.Instance.EstimationCache.LocalGet(this.Id);
}
}
private ObservableCollection<Estimate> estimates;
public ObservableCollection<Estimate> Estimates {
get {
return estimates;
} }
public bool EstimationDone
{
get
{
return Estimates != null && Estimates.Count>0;
}
}
public string EditEstimateButtonText
{
get
{
return DraftEstimate != null ?
Strings.EditEstimate : Strings.DoEstimate;
}
}
bool rejected = false;
public bool Rejected { get
{
return rejected;
}
set
{
SetProperty<bool>(ref rejected, value);
}
}
}
}

View file

@ -0,0 +1,159 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using Newtonsoft.Json;
using System.Linq;
using System.ComponentModel;
namespace BookAStar.ViewModels.EstimateAndBilling
{
using Model;
using Model.Workflow;
using Model.Social;
using Validation;
public class EditEstimateViewModel : EditingViewModel<Estimate>
{
/// <summary>
/// Builds a new view model on estimate,
/// sets <c>Data</c> with given value parameter
/// </summary>
/// <param name="data"></param>
/// <param name="localState"></param>
public EditEstimateViewModel(Estimate data) : base(data)
{
SyncData();
}
public override void OnViewAppearing()
{
base.OnViewAppearing();
SyncData();
}
/// <summary>
/// Called to synchronyze this view on target model,
/// at accepting a new representation for this model
/// </summary>
private void SyncData()
{
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");
NotifyPropertyChanged("ModelState");
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.PropertyName.StartsWith("Data"))
{
SyncData();
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Bill_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Data.Bill = Bill.Select(l => l.Data).ToList();
NotifyPropertyChanged("FormattedTotal");
NotifyPropertyChanged("Bill");
NotifyPropertyChanged("ViewModelState");
}
[JsonIgnore]
public ObservableCollection<string> AttachedFiles
{
get; protected set;
}
[JsonIgnore]
public ObservableCollection<string> AttachedGraphicList
{
get; protected set;
}
[JsonIgnore]
public ObservableCollection<BillingLineViewModel> Bill
{
get; protected set;
}
[JsonIgnore]
private string description;
public string Description
{
get
{
return description;
}
set
{
SetProperty<string>(ref description, value);
Data.Description = description;
}
}
private string title;
[JsonIgnore]
public string Title
{
get
{
return title;
}
set
{
SetProperty<string>(ref title, value, "Title");
Data.Title = title;
}
}
[JsonIgnore]
public ClientProviderInfo Client { get { return Data.Client; } }
[JsonIgnore]
public BookQuery Query { get { return Data.Query; } }
[JsonIgnore]
public FormattedString FormattedTotal
{
get
{
/*
OnPlatform<Font> lfs = (OnPlatform<Font>)App.Current.Resources["MediumFontSize"];
*/
OnPlatform<double> mfs = (OnPlatform < double > ) App.Current.Resources["MediumFontSize"];
Color etc = (Color) App.Current.Resources["EmphasisTextColor"];
return new FormattedString
{
Spans = {
new Span { Text = "Total TTC: " },
new Span { Text = Data.Total.ToString(),
ForegroundColor = etc,
FontSize = mfs },
new Span { Text = "€", FontSize = mfs }
}
};
}
}
}
}

View file

@ -0,0 +1,14 @@
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels
{
using EstimateAndBilling;
using UserProfile;
public class HomeViewModel : ViewModel
{
public BookQueriesViewModel BookQueries { get; set; }
public UserProfileViewModel UserProfile { get; set; }
}
}

View file

@ -0,0 +1,46 @@
using BookAStar.Data;
using BookAStar.Model.Social.Chat;
using BookAStar.Model.Social.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace BookAStar.ViewModels.Messaging
{
public class ChatUserCollection : RemoteEntityRO<ChatUserInfo, string>
{
public ChatUserCollection() : base ("chat/users", u=>u.UserId)
{
}
public void OnPrivateMessage(ChatMessage msg)
{
var sender = this.FirstOrDefault(user => user.UserName == msg.SenderId);
if (sender != null)
{
sender.PrivateMessages.Add(msg);
} else
{
// TODO alert? or else get chat user info
// or else just display this message ...
}
}
public override void Merge(ChatUserInfo item)
{
var key = GetKey(item);
var existent = this.FirstOrDefault(u => u.UserId == key);
if (existent != null) {
existent.UserName = item.UserName;
existent.Roles = item.Roles;
existent.Avatar = item.Avatar;
existent.Connections = item.Connections;
}
else Add(item);
}
}
}

View file

@ -0,0 +1,196 @@

using BookAStar.Helpers;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
using XLabs.Forms.Mvvm;
using YavscLib;
using System;
using Newtonsoft.Json;
using BookAStar.Model.Social.Messaging;
namespace BookAStar.Model.Social.Chat
{
public class ChatUserInfo : ViewModel, IChatUserInfo
{
public ChatUserInfo()
{
PrivateMessages.CollectionChanged += PrivateMessages_CollectionChanged;
}
private void PrivateMessages_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
NotifyPropertyChanged("Unread");
}
public string avatar;
public string Avatar
{
get
{
return avatar;
}
set
{
var newSource = UserHelpers.Avatar(value);
SetProperty<string>(ref avatar, value);
SetProperty<ImageSource>(ref avatarSource, newSource, "AvatarSource");
}
}
ImageSource avatarSource;
[JsonIgnore]
public ImageSource AvatarSource
{
get
{
return avatarSource;
}
}
public Connection [] Connections
{
get
{
return ObservableConnections?.ToArray();
}
set
{
ObservableConnections = new ObservableCollection<Connection>(value);
}
}
ObservableCollection<Connection> connections;
[JsonIgnore]
public ObservableCollection<Connection> ObservableConnections
{
get
{
return connections;
}
set
{
SetProperty<ObservableCollection<Connection>>(ref connections, value);
}
}
string[] roles;
public string[] Roles
{
get
{
return roles;
}
set
{
SetProperty<string[]>(ref roles, value);
NotifyPropertyChanged("RolesAsAString");
}
}
[JsonIgnore]
public string RolesAsAString
{
get
{
return Roles == null? "": string.Join(", ", Roles);
}
}
string userId;
public string UserId
{
get
{
return userId;
}
set
{
SetProperty<string>(ref userId, value);
}
}
string userName;
public string UserName
{
get
{
return userName;
}
set
{
SetProperty<string>(ref userName, value);
}
}
public bool IsConnected { get
{
return Connections.Length > 0;
} }
[JsonIgnore]
IConnection[] IChatUserInfo.Connections
{
get
{
return Connections;
}
set
{
throw new NotImplementedException();
}
}
ObservableCollection<ChatMessage> privateMessages = new ObservableCollection<ChatMessage>();
[JsonIgnore]
public ObservableCollection<ChatMessage> PrivateMessages
{
get
{
return privateMessages;
}
}
[JsonIgnore]
public bool Unread
{
get
{
return PrivateMessages==null?false: PrivateMessages.Any(
m => !m.Read);
}
}
[JsonIgnore]
public ImageSource MessagesBadge
{
get
{
return Unread ? ImageSource.FromResource("BookAStar.Images.Chat.talk.png") :null;
}
}
public void OnConnected(string cxId)
{
// We do assume this cxId dosn't already exist in this list.
var cx = new Connection { ConnectionId = cxId, Connected = true };
if (ObservableConnections == null)
ObservableConnections = new ObservableCollection<Connection>();
ObservableConnections.Add(cx);
if (this.ObservableConnections.Count == 1)
NotifyPropertyChanged("IsConnected");
}
public void OnDisconnected(string cxId)
{
var existentcx = Connections.FirstOrDefault(cx => cx.ConnectionId == cxId);
if (existentcx != null)
{
this.ObservableConnections.Remove(existentcx);
if (this.ObservableConnections.Count == 0)
NotifyPropertyChanged("IsConnected");
}
}
}
}

View file

@ -0,0 +1,98 @@
using Microsoft.AspNet.SignalR.Client;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.Messaging
{
using Data;
using Model.Social.Chat;
using Model.Social.Messaging;
public class ChatViewModel: ViewModel
{
public ObservableCollection<ChatMessage> Messages { get; set; }
public ObservableCollection<ChatMessage> Notifs { get; set; }
public ChatUserCollection ChatUsers { get; set; }
private ConnectionState state;
public ConnectionState State
{
get { return state; }
}
public ChatViewModel()
{
App.ChatHubConnection.StateChanged += ChatHubConnection_StateChanged;
MainSettings.UserChanged += MainSettings_UserChanged;
Messages = new ObservableCollection<ChatMessage>();
Notifs = new ObservableCollection<ChatMessage>();
ChatUsers = DataManager.Instance.ChatUsers;
App.ChatHubProxy.On<string, string>("addMessage", (n, m) =>
{
Messages.Add(new ChatMessage
{
Message = m,
SenderId = n,
Date = DateTime.Now
});
});
App.ChatHubProxy.On<string, string, string>("notify", (eventId, cxId, userName) =>
{
var msg = new ChatMessage
{
Message = eventId,
SenderId = userName,
Date = DateTime.Now
};
// TODO make admin possible
// by assigning a server side username to anonymous.
if (string.IsNullOrEmpty(userName))
{
msg.SenderId = $"({cxId})";
}
Notifs.Add(msg);
if (eventId == "connected")
OnUserConnected(cxId, userName);
else if (eventId == "disconnected")
OnUserDisconnected(cxId, userName);
});
}
private void OnUserConnected(string cxId, string userName)
{
var user = ChatUsers.SingleOrDefault(
c => c.UserName == userName);
if (user == null)
{
user = new ChatUserInfo {
UserName = userName
};
ChatUsers.Add(user);
}
user.OnConnected(cxId);
}
private void OnUserDisconnected (string cxId, string userName)
{
var user = ChatUsers.SingleOrDefault(
c => c.UserName == userName);
if (user == null)
{
return;
}
user.OnDisconnected(cxId);
}
private void MainSettings_UserChanged(object sender, EventArgs e)
{
}
private void ChatHubConnection_StateChanged(StateChange obj)
{
SetProperty<ConnectionState>(ref state, obj.NewState, "State");
}
}
}

View file

@ -0,0 +1,12 @@
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels
{
internal class PageState
{
internal int Position { get; set; }
internal object BindingContext { get; set; }
internal string PageType { get; set; }
}
}

View file

@ -0,0 +1,10 @@

using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.Searching
{
class SearchingAnArtistViewModel: ViewModel
{
}
}

View file

@ -0,0 +1,68 @@
using BookAStar.Model.Workflow;
using BookAStar.ViewModels.EstimateAndBilling;
using Xamarin.Forms;
namespace BookAStar.ViewModels.Signing
{
public class EstimateSigningViewModel: EditEstimateViewModel
{
public EstimateSigningViewModel(Estimate document): base(document)
{
}
public Command<bool> ValidationCommand { get; set; }
public ImageSource ProSignImage {
get
{
return new FileImageSource();
}
}
public ImageSource CliSignImage
{
get
{
return new FileImageSource();
}
}
private bool isClientView=false;
public bool IsClientView {
get
{
return isClientView;
}
set {
bool old = isClientView;
SetProperty<bool>(ref isClientView, value);
if (old!=value)
{
if (value != !isProviderView)
IsProviderView = !value;
}
}
}
private bool isProviderView=true;
public bool IsProviderView
{
get
{
return isProviderView;
}
set
{
bool old = isProviderView;
SetProperty<bool>(ref isProviderView, value);
if (old != value)
{
if (value != !isClientView)
IsClientView = !value;
}
}
}
}
}

View file

@ -0,0 +1,160 @@
using Xamarin.Forms;
using System.Windows.Input;
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.Signing
{
using Model.Settings;
public class SignaturePadConfigViewModel : ViewModel
{
private readonly ICommand isConfiguringCommand;
private bool isConfiguring;
private string captionText;
private string clearText;
private string promptText;
private int strokeWidth;
private Color captionTextColor;
private Color clearTextColor;
private Color promptTextColor;
private Color signaturePadBackground;
private Color signatureLineColor;
private Color strokeColor;
public SignaturePadConfigViewModel()
{
isConfiguringCommand = new Command(() => IsConfiguring = !IsConfiguring);
}
public ICommand ConfigureCommand => isConfiguringCommand;
public bool IsConfiguring
{
get { return isConfiguring; }
set { SetProperty<bool>(ref isConfiguring, value); }
}
public string CaptionText
{
get { return captionText; }
set { SetProperty(ref captionText, value); }
}
public string ClearText
{
get { return clearText; }
set { SetProperty(ref clearText, value); }
}
public string PromptText
{
get { return promptText; }
set { SetProperty(ref promptText, value); }
}
public Color CaptionTextColor
{
get { return captionTextColor; }
set { if (SetProperty(ref captionTextColor, value))
NotifyPropertyChanged(nameof(CaptionTextColorIndex)); }
}
public Color ClearTextColor
{
get { return clearTextColor; }
set { if (SetProperty(ref clearTextColor, value))
NotifyPropertyChanged(nameof(ClearTextColorIndex)); }
}
public Color PromptTextColor
{
get { return promptTextColor; }
set { if (SetProperty(ref promptTextColor, value))
NotifyPropertyChanged(nameof(PromptTextColorIndex)); }
}
public Color SignaturePadBackground
{
get { return signaturePadBackground; }
set { if (SetProperty(ref signaturePadBackground, value))
NotifyPropertyChanged(nameof(SignaturePadBackgroundIndex)); }
}
public Color SignatureLineColor
{
get { return signatureLineColor; }
set { if (SetProperty(ref signatureLineColor, value))
NotifyPropertyChanged(nameof(SignatureLineColorIndex)); }
}
public Color StrokeColor
{
get { return strokeColor; }
set { if (SetProperty(ref strokeColor, value))
NotifyPropertyChanged(nameof(StrokeColorIndex)); }
}
public int StrokeWidth
{
get { return strokeWidth; }
set { SetProperty(ref strokeWidth, value); }
}
public int CaptionTextColorIndex
{
get { return SignatureSettings.Colors.IndexOf(CaptionTextColor); }
set { CaptionTextColor = SignatureSettings.Colors[value]; }
}
public int ClearTextColorIndex
{
get { return SignatureSettings.Colors.IndexOf(ClearTextColor); }
set { ClearTextColor = SignatureSettings.Colors[value]; }
}
public int PromptTextColorIndex
{
get { return SignatureSettings.Colors.IndexOf(PromptTextColor); }
set { PromptTextColor = SignatureSettings.Colors[value]; }
}
public int SignaturePadBackgroundIndex
{
get { return SignatureSettings.Colors.IndexOf(SignaturePadBackground); }
set { SignaturePadBackground = SignatureSettings.Colors[value]; }
}
public int SignatureLineColorIndex
{
get { return SignatureSettings.Colors.IndexOf(SignatureLineColor); }
set { SignatureLineColor = SignatureSettings.Colors[value]; }
}
public int StrokeColorIndex
{
get { return SignatureSettings.Colors.IndexOf(StrokeColor); }
set { StrokeColor = SignatureSettings.Colors[value]; }
}
public override void OnViewAppearing()
{
IsConfiguring = true;
CaptionText = "signez ici";
ClearText = "éffacer";
PromptText = ">";
StrokeWidth = 2;
CaptionTextColor = Color.Gray;
ClearTextColor = Color.Gray;
PromptTextColor = Color.Gray;
SignaturePadBackground = Color.Yellow;
SignatureLineColor = Color.Black;
StrokeColor = Color.Black;
base.OnViewAppearing();
}
}
}

View file

@ -0,0 +1,237 @@
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
using XLabs.Forms.Behaviors;
using XLabs.Forms.Controls;
using XLabs.Forms.Mvvm;
using XLabs.Ioc;
using XLabs.Platform.Services;
namespace BookAStar.ViewModels.UserProfile
{
using Data;
using Helpers;
using Model.Auth.Account;
using Pages.UserProfile;
using System.Threading.Tasks;
internal class DashboardViewModel : ViewModel
{
public string UserFilesLabel
{
get; set;
}
int rating;
public int Rating
{
get
{
return rating;
}
set
{
SetProperty<int>(ref rating, value, "Rating");
}
}
public string UserId
{
get
{
return User?.Id;
}
}
public bool AllowUseMyPosition
{
get
{
return MainSettings.AllowGPSUsage;
}
set
{
MainSettings.AllowGPSUsage = value;
}
}
public bool AllowProBookingOnly
{
get
{
return MainSettings.AllowProBookingOnly;
}
set
{
MainSettings.AllowProBookingOnly = value;
}
}
public bool ReceivePushNotifications
{
get
{
return MainSettings.PushNotifications;
}
set
{
MainSettings.PushNotifications = value;
}
}
private long queryCount;
private User user;
public long QueryCount
{
get
{
return queryCount;
}
}
public User User
{
get { return user; }
protected set
{
SetProperty<User>(ref user, value, "User");
if (user!=null)
{
user.PropertyChanged += User_PropertyChanged;
}
UpdateUserMeta();
}
}
private ImageSource avatar;
public ImageSource Avatar { get {
return avatar;
} }
public ObservableCollection<User> Accounts { get; protected set; }
private string performerStatus;
public string PerformerStatus
{
get
{
return performerStatus;
}
}
string userQueries;
public string UserQueries
{
get
{
return userQueries;
}
}
public string UserName
{
get
{
return User?.UserName;
}
}
private bool userIsPro = false;
public DashboardViewModel()
{
Accounts = MainSettings.AccountList;
User = MainSettings.CurrentUser;
UpdateUserMeta();
Rating = 2;
UserNameGesture = new RelayGesture((g, x) =>
{
if (g.GestureType == GestureType.LongPress)
{
Navigation.PushAsync(App.UserProfilePage);
}
});
MainSettings.UserChanged += MainSettings_UserChanged;
}
private void MainSettings_UserChanged(object sender, System.EventArgs e)
{
User = MainSettings.CurrentUser;
UpdateUserMeta();
}
bool haveAnUser;
public bool HaveAnUser
{
get { return User!=null; }
}
public bool UserIsPro
{
get { return User?.Roles?.Contains("Performer") ?? false ; }
}
private void UpdateUserMeta ()
{
Task.Run( ()=> {
string newStatusString;
long newQueryCount;
bool newUserIsPro;
ImageSource newAvatar;
string newQueriesButtonText;
bool userIsNull = user == null;
if (userIsNull)
{
newQueryCount = 0;
newUserIsPro = false;
newStatusString = "no user selected";
newAvatar = null;
newQueriesButtonText = "no user selected";
}
else
{
newUserIsPro = UserIsPro;
newQueryCount = newUserIsPro ? DataManager.Instance.BookQueries.Count : 0;
newStatusString = newUserIsPro ?
$"Profile professionel renseigné" :
"Profile professionel non renseigné";
newQueriesButtonText = newUserIsPro ?
$"{newQueryCount} demandes valides en cours" :
"Profile professionel non renseigné";
newAvatar = UserHelpers.Avatar(user.Avatar);
}
SetProperty<bool>(ref haveAnUser, userIsNull, "HaveAnUser");
SetProperty<bool>(ref userIsPro, newUserIsPro, "UserIsPro");
SetProperty<string>(ref performerStatus, newStatusString, "PerformerStatus");
SetProperty<string>(ref userQueries, newQueriesButtonText, "UserQueries");
SetProperty<long>(ref queryCount, newQueryCount, "QueryCount");
try
{
SetProperty<ImageSource>(ref avatar, newAvatar, "Avatar");
}
catch (TaskCanceledException)
{ }
NotifyPropertyChanged("UserName");
NotifyPropertyChanged("UserId");
});
}
private void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
UpdateUserMeta();
}
public RelayGesture UserNameGesture { get; set; }
public string UserFilesText
{
get
{
return Strings.YourFiles;
}
}
}
}

View file

@ -0,0 +1,75 @@

using System.Collections.ObjectModel;
using System.Windows.Input;
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.UserProfile
{
using System.ComponentModel;
using Model.FileSystem;
public class DirectoryInfoViewModel : ViewModel
{
private string subPath;
public string SubPath
{
get { return subPath; }
set { SetProperty<string>(ref subPath, value); }
}
private string userName;
public string UserName
{
get { return userName; }
set { SetProperty<string>(ref userName, value); }
}
private ObservableCollection<string> subDirectories;
public ObservableCollection<string> SubDirectories
{
get { return subDirectories; }
set { SetProperty< ObservableCollection < string >>( ref subDirectories, value) ; }
}
private ObservableCollection<UserFileInfo> fileInfo;
public ObservableCollection<UserFileInfo> FileInfo
{
get { return fileInfo; }
set { SetProperty<ObservableCollection<UserFileInfo>> ( ref fileInfo, value ); }
}
UserDirectoryInfo model;
public UserDirectoryInfo InnerModel {
get { return model; }
set {
if (SetProperty<UserDirectoryInfo>(ref model, value))
if (model == null)
{
SubDirectories = new ObservableCollection<string>();
FileInfo = new ObservableCollection<UserFileInfo>();
SubPath = "<no path>";
UserName = "<no user>";
}
else
{
SubDirectories = new ObservableCollection<string>(model.SubDirectories);
FileInfo = new ObservableCollection<UserFileInfo>(model.Files);
SubPath = model.SubPath;
UserName = model.UserName;
}
}
}
public DirectoryInfoViewModel(UserDirectoryInfo model = null)
{
this.InnerModel = model;
}
private ICommand refreshCommand;
public ICommand RefreshCommand
{
get { return refreshCommand; }
set { SetProperty<ICommand>(ref refreshCommand, value); }
}
}
}

View file

@ -0,0 +1,10 @@
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.UserProfile
{
class UserLoginViewModel : ViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
}

View file

@ -0,0 +1,225 @@
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
using XLabs.Forms.Behaviors;
using XLabs.Forms.Controls;
using XLabs.Forms.Mvvm;
using XLabs.Ioc;
using XLabs.Platform.Services;
namespace BookAStar.ViewModels.UserProfile
{
using Data;
using Helpers;
using Model.Auth.Account;
using Pages.UserProfile;
public class UserProfileViewModel : ViewModel
{
public bool IsAPerformer
{
get { return User?.Roles?.Contains("Performer") ?? false; }
}
public string UserFilesLabel
{
get; set;
}
// TODO implementation
int rating ;
public int Rating
{
get
{
return rating;
}
set
{
SetProperty<int>(ref rating, value, "Rating");
}
}
private bool allowUseMyPosition = MainSettings.AllowGPSUsage;
public bool AllowUseMyPosition
{
get
{
return allowUseMyPosition;
}
set
{
MainSettings.AllowGPSUsage = value;
SetProperty<bool>(ref allowUseMyPosition, value);
}
}
private bool allowProBookingOnly = MainSettings.AllowProBookingOnly;
public bool AllowProBookingOnly
{
get
{
return allowProBookingOnly;
}
set
{
MainSettings.AllowProBookingOnly = value;
SetProperty<bool>(ref allowUseMyPosition, value);
}
}
bool receivePushNotifications = MainSettings.PushNotifications;
public bool ReceivePushNotifications
{
get
{
return receivePushNotifications;
}
set
{
MainSettings.PushNotifications = value;
SetProperty<bool>(ref receivePushNotifications, value);
}
}
private long queryCount;
private User user;
public long QueryCount
{
get
{
return queryCount;
}
}
public User User
{
get { return user; }
protected set
{
SetProperty<User>(ref user, value, "User");
if (user!=null)
{
user.PropertyChanged += User_PropertyChanged;
}
UpdateUserMeta();
}
}
private ImageSource avatar;
public ImageSource Avatar { get {
return avatar;
} }
public ObservableCollection<User> Accounts { get; protected set; }
private string performerStatus;
public string PerformerStatus
{
get
{
return performerStatus;
}
}
string userQueries;
public string UserQueries
{
get
{
return userQueries;
}
}
public string UserName
{
get
{
return User?.UserName;
}
}
private bool userIsPro = false;
public UserProfileViewModel()
{
Accounts = MainSettings.AccountList;
User = MainSettings.CurrentUser;
UpdateUserMeta();
Rating = 2;
UserNameGesture = new RelayGesture((g, x) =>
{
if (g.GestureType == GestureType.LongPress)
{
NavigationService.NavigateTo("accountChooser");
}
});
MainSettings.UserChanged += MainSettings_UserChanged;
}
private void MainSettings_UserChanged(object sender, System.EventArgs e)
{
User = MainSettings.CurrentUser;
UpdateUserMeta();
}
bool haveAnUser;
public bool HaveAnUser
{
get { return User!=null; }
}
private void UpdateUserMeta ()
{
string newStatusString;
long newQueryCount;
bool newUserIsPro;
ImageSource newAvatar;
string newQueriesButtonText;
bool newHaveAnUser = user == null;
if (newHaveAnUser) {
newQueryCount = 0;
newUserIsPro = false;
newStatusString = null;
newAvatar = null;
newQueriesButtonText = null;
}
else
{
newUserIsPro = IsAPerformer;
newQueryCount = newUserIsPro ? DataManager.Instance.BookQueries.Count : 0;
newStatusString = newUserIsPro ?
$"Profile professionel renseigné" :
"Profile professionel non renseigné";
newQueriesButtonText = newUserIsPro ?
$"{newQueryCount} demandes valides en cours" :
"Profile professionel non renseigné";
newAvatar = UserHelpers.Avatar(user.Avatar);
}
SetProperty<bool>(ref haveAnUser, newHaveAnUser, "HaveAnUser");
SetProperty<string>(ref performerStatus, newStatusString, "PerformerStatus");
SetProperty<string>(ref userQueries, newQueriesButtonText, "UserQueries");
SetProperty<long>(ref queryCount, newQueryCount, "QueryCount");
SetProperty<ImageSource>(ref avatar, newAvatar, "Avatar");
NotifyPropertyChanged("UserName");
NotifyPropertyChanged("AllowProBookingOnly");
NotifyPropertyChanged("AllowUseMyPosition");
NotifyPropertyChanged("ReceivePushNotifications");
NotifyPropertyChanged("AllowUseMyPosition");
NotifyPropertyChanged("IsAPerformer");
}
private void User_PropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
UpdateUserMeta();
}
public RelayGesture UserNameGesture { get; set; }
}
}

View file

@ -0,0 +1,81 @@
using System;
using XLabs.Forms.Mvvm;
using System.ComponentModel;
using Newtonsoft.Json;
namespace BookAStar.ViewModels.Validation
{
/// <summary>
/// Used to make the DataManager know how
/// to sync local and remote data
/// </summary>
public class EditingViewModel<DataType>: ViewModel
{
[JsonIgnore]
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);
Check();
}
public virtual void Check()
{
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);
}
}
*/
}
}

View file

@ -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; }
}
}

View file

@ -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
}
}

View file

@ -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);
}
}
}

View file

@ -0,0 +1,46 @@
using BookAStar.Helpers;
using BookAStar.Interfaces;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace BookAStar.ViewModels
{
[Obsolete("Use legacy XLabs ViewModel")]
public class ViewModelBase : IModelViewModel
{
public string Title { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void SetState<T>(Action<T> action) where T : class, IModelViewModel
{
action(this as T);
}
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
OnPropertyChanged( PropertySupport.ExtractPropertyName<T>( propertyExpression));
}
}
}