un positionnement de paramètre workflow des pros
This commit is contained in:
@ -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
|
||||
|
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Accounts;
|
||||
|
||||
namespace BookAStar.Droid.Accounts
|
||||
{
|
||||
class YavscAccountAuthenticator : AbstractAccountAuthenticator
|
||||
{
|
||||
public YavscAccountAuthenticator(Context context): base(context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override Bundle AddAccount(AccountAuthenticatorResponse response, string accountType, string authTokenType, string[] requiredFeatures, Bundle options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Bundle ConfirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Bundle EditProperties(AccountAuthenticatorResponse response, string accountType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Bundle GetAuthToken(AccountAuthenticatorResponse response, Account account, string authTokenType, Bundle options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string GetAuthTokenLabel(string authTokenType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Bundle HasFeatures(AccountAuthenticatorResponse response, Account account, string[] features)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Bundle UpdateCredentials(AccountAuthenticatorResponse response, Account account, string authTokenType, Bundle options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;DEV</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>0</WarningLevel>
|
||||
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
|
||||
@ -328,6 +328,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Accounts\YavscAccountAuthenticator.cs" />
|
||||
<Compile Include="Helpers\Settings.cs" />
|
||||
<Compile Include="Helpers\SimpleJsonPostMethod.cs" />
|
||||
<Compile Include="Helpers\YavscHelpers.cs" />
|
||||
@ -342,11 +343,14 @@
|
||||
<Compile Include="Markdown\MarkdownViewModel.cs" />
|
||||
<Compile Include="Markdown\MarkdownViewRenderer.cs" />
|
||||
<Compile Include="Markdown\MarkdownWebChromeClient.cs" />
|
||||
<Compile Include="Markdown\MDContextMenu.cs" />
|
||||
<Compile Include="Markdown\MDWebView.cs" />
|
||||
<Compile Include="OAuth2\YaOAuth2Authenticator.cs" />
|
||||
<Compile Include="Rendering\ImageButtonRenderer.cs" />
|
||||
<Compile Include="Resources\Resource.Designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SendFilesActivity.cs" />
|
||||
<Compile Include="Services\AccountChooserService.cs" />
|
||||
<Compile Include="Services\YavscChooserTargetService.cs" />
|
||||
<Compile Include="Services\GcmListenerService.cs" />
|
||||
<Compile Include="Services\GcmRegistrationIntentService.cs" />
|
||||
@ -372,6 +376,9 @@
|
||||
<AndroidResource Include="Resources\layout\EditEstimate.axml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\menu\md_menu.axml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\icon.png" />
|
||||
@ -381,15 +388,17 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\Tabbar.axml" />
|
||||
<AndroidResource Include="Resources\layout\Toolbar.axml" />
|
||||
<AndroidResource Include="Resources\layout\Toolbar.axml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\values\styles.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</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>
|
||||
@ -474,7 +483,9 @@
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\values\dimens.xml" />
|
||||
<AndroidResource Include="Resources\values\strings.xml" />
|
||||
<AndroidResource Include="Resources\values\strings.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\drawable\glyphish_07_map_marker.png" />
|
||||
<AndroidResource Include="Resources\drawable\glyphish_13_target.png" />
|
||||
<AndroidResource Include="Resources\drawable\glyphish_74_location.png" />
|
||||
@ -499,6 +510,14 @@
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\peer_to_peer.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\xml\authenticator.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\xml\account_preferences.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
@ -251,8 +251,8 @@ namespace BookAStar.Droid
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
App.ShowBookQuery(
|
||||
await DataManager.Current.BookQueries.Get(queryId));
|
||||
var query = DataManager.Instance.BookQueries.LocalGet(queryId);
|
||||
App.ShowBookQuery(query);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -319,15 +319,16 @@ namespace BookAStar.Droid
|
||||
return manager.FindAccountsForService(Constants.ApplicationName);
|
||||
});
|
||||
}
|
||||
YaOAuth2Authenticator auth = new YaOAuth2Authenticator(
|
||||
clientId: "d9be5e97-c19d-42e4-b444-0e65863b19e1",
|
||||
clientSecret: "blouh",
|
||||
scope: "profile",
|
||||
authorizeUrl: new Uri("http://dev.pschneider.fr/authorize"),
|
||||
redirectUrl: new Uri("http://dev.pschneider.fr/oauth/success"),
|
||||
accessTokenUrl: new Uri("http://dev.pschneider.fr/token"));
|
||||
|
||||
public void AddAccount()
|
||||
{
|
||||
var auth = new YaOAuth2Authenticator(
|
||||
clientId: "d9be5e97-c19d-42e4-b444-0e65863b19e1",
|
||||
clientSecret: "blouh",
|
||||
scope: "profile",
|
||||
authorizeUrl: new Uri(Constants.AuthorizeUrl),
|
||||
redirectUrl: new Uri(Constants.RedirectUrl),
|
||||
accessTokenUrl: new Uri(Constants.AccessTokenUrl));
|
||||
Intent loginIntent = auth.GetUI(this);
|
||||
var accStore = AccountStore.Create(this);
|
||||
auth.Completed += (sender, eventArgs) =>
|
||||
@ -348,65 +349,48 @@ namespace BookAStar.Droid
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
|
||||
// get me
|
||||
// var request = new OAuth2Request("GET", new Uri(Constants.UserInfoUrl), null, eventArgs.Account);
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl);
|
||||
|
||||
request.Headers.Authorization =
|
||||
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokens.AccessToken);
|
||||
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
string userJson = await response.Content.ReadAsStringAsync();
|
||||
JObject jactiveUser = JObject.Parse(userJson);
|
||||
Account acc = eventArgs.Account;
|
||||
|
||||
var uid = jactiveUser["Id"].Value<string>();
|
||||
var username = jactiveUser["UserName"].Value<string>();
|
||||
var roles = jactiveUser["Roles"].Values<string>().ToList();
|
||||
var emails = jactiveUser["EMails"].Values<string>().ToList();
|
||||
|
||||
|
||||
var newuser = new User
|
||||
using (var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl))
|
||||
{
|
||||
UserName = username,
|
||||
EMails = emails,
|
||||
Roles = roles,
|
||||
Id = uid,
|
||||
YavscTokens = tokens
|
||||
};
|
||||
request.Headers.Authorization =
|
||||
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokens.AccessToken);
|
||||
|
||||
MainSettings.SaveUser(newuser);
|
||||
accStore.Save(acc, Constants.ApplicationName);
|
||||
using (var response = await client.SendAsync(request))
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
string userJson = await response.Content.ReadAsStringAsync();
|
||||
JObject jactiveUser = JObject.Parse(userJson);
|
||||
Account acc = eventArgs.Account;
|
||||
|
||||
var uid = jactiveUser["Id"].Value<string>();
|
||||
var username = jactiveUser["UserName"].Value<string>();
|
||||
var roles = jactiveUser["Roles"].Values<string>().ToList();
|
||||
var emails = jactiveUser["EMails"].Values<string>().ToList();
|
||||
var avatar = jactiveUser["Avatar"].Value<string>();
|
||||
var address = jactiveUser["Avatar"].Value<string>();
|
||||
var newuser = new User
|
||||
{
|
||||
UserName = username,
|
||||
EMails = emails,
|
||||
Roles = roles,
|
||||
Id = uid,
|
||||
YavscTokens = tokens,
|
||||
Avatar = avatar,
|
||||
Address = address
|
||||
};
|
||||
|
||||
MainSettings.SaveUser(newuser);
|
||||
accStore.Save(acc, Constants.ApplicationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
auth.Error += Auth_Error;
|
||||
StartActivity(loginIntent);
|
||||
}
|
||||
|
||||
public static void PopulateUserWithAccount(User u, Account a)
|
||||
{
|
||||
u.YavscTokens = new Model.Auth.Account.Tokens
|
||||
{
|
||||
AccessToken =
|
||||
a.Properties["access_token"],
|
||||
RefreshToken =
|
||||
a.Properties["refresh_token"],
|
||||
ExpiresIn =
|
||||
int.Parse(a.Properties["expires_in"]),
|
||||
TokenType = a.Properties["token_type"]
|
||||
};
|
||||
u.UserName = a.Username;
|
||||
}
|
||||
|
||||
private void Auth_Error(object sender, AuthenticatorErrorEventArgs e)
|
||||
{
|
||||
// TODO handle
|
||||
|
73
BookAStar/BookAStar.Droid/Markdown/MDContextMenu.cs
Normal file
73
BookAStar/BookAStar.Droid/Markdown/MDContextMenu.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Support.V7.App;
|
||||
using XLabs.Ioc;
|
||||
using XLabs.Platform.Mvvm;
|
||||
using XLabs.Forms;
|
||||
using static Android.Views.View;
|
||||
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
class MDContextMenu : AppCompatDialog
|
||||
{
|
||||
private ActionMode mActionMode = null;
|
||||
public MDContextMenu(Context context) : base(context)
|
||||
{
|
||||
|
||||
}
|
||||
public override void OnActionModeStarted(ActionMode mode)
|
||||
{
|
||||
if (mActionMode == null)
|
||||
{
|
||||
mActionMode = mode;
|
||||
var menu = mode.Menu;
|
||||
// Remove the default menu items (select all, copy, paste, search)
|
||||
menu.Clear();
|
||||
|
||||
// If you want to keep any of the defaults,
|
||||
// remove the items you don't want individually:
|
||||
// menu.removeItem(android.R.id.[id_of_item_to_remove])
|
||||
|
||||
// Inflate your own menu items
|
||||
mode.MenuInflater.Inflate(Resource.Menu.md_menu, menu);
|
||||
|
||||
}
|
||||
mActionMode = mode;
|
||||
base.OnActionModeStarted(mode);
|
||||
}
|
||||
public override void OnActionModeFinished(ActionMode mode)
|
||||
{
|
||||
base.OnActionModeFinished(mode);
|
||||
}
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
}
|
||||
public void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
|
||||
{
|
||||
/* if (menuInfo!=null)
|
||||
{
|
||||
var info = menuInfo.ToString();
|
||||
}
|
||||
menu.Add(0, 0, 0, "test");
|
||||
var subMenu = menu.AddSubMenu(
|
||||
0, 1, 1, "...");
|
||||
subMenu.Add(0, 3, 0, "nkjnkjn");
|
||||
var app = Resolver.Resolve<IXFormsApp>() as IXFormsApp<XFormsCompatApplicationDroid>;
|
||||
|
||||
var mgr = ClipboardManager.FromContext(app.AppContext);
|
||||
if (mgr.HasText)
|
||||
menu.Add(0, 0, 0, "Coller!");*/
|
||||
//base.OnCreateContextMenu(menu, v, menuInfo);
|
||||
}
|
||||
}
|
||||
}
|
28
BookAStar/BookAStar.Droid/Markdown/MDWebView.cs
Normal file
28
BookAStar/BookAStar.Droid/Markdown/MDWebView.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Webkit;
|
||||
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
class MDWebView : WebView
|
||||
{
|
||||
public MDWebView (Context context) : base (context)
|
||||
{
|
||||
}
|
||||
|
||||
public override ActionMode StartActionMode(ActionMode.ICallback callback)
|
||||
{
|
||||
return base.StartActionMode(callback);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorTemplatePreprocessor", "4.2.0.703")]
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorTemplatePreprocessor", "4.2.1.62")]
|
||||
public partial class MarkdownEditor : MarkdownEditorBase
|
||||
{
|
||||
|
||||
|
@ -9,6 +9,7 @@ using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Graphics;
|
||||
|
||||
namespace BookAStar.Droid.Markdown
|
||||
{
|
||||
@ -17,6 +18,7 @@ namespace BookAStar.Droid.Markdown
|
||||
protected static MarkdownDeep.Markdown markdown = new MarkdownDeep.Markdown();
|
||||
public string Content { get; set; }
|
||||
public bool Editable { get; set; }
|
||||
|
||||
public string GetHtml()
|
||||
{
|
||||
return markdown.Transform(Content);
|
||||
|
@ -12,6 +12,11 @@ using Android.Views;
|
||||
namespace BookAStar.Droid
|
||||
{
|
||||
using Markdown;
|
||||
using XLabs.Forms;
|
||||
using XLabs.Ioc;
|
||||
using XLabs.Platform.Mvvm;
|
||||
using static View;
|
||||
|
||||
public class MarkdownViewRenderer : ViewRenderer<MarkdownView, WebView>
|
||||
{
|
||||
private WebView editorView;
|
||||
@ -35,7 +40,9 @@ namespace BookAStar.Droid
|
||||
{
|
||||
if (view == null || xview == null) return;
|
||||
var vch = view.ContentHeight;
|
||||
xview.HeightRequest = vch > xview.MinimumHeightRequest ? vch : xview.MinimumHeightRequest;
|
||||
// var oldH = xview.Height;
|
||||
var newH = vch > xview.MinimumHeightRequest ? vch : xview.MinimumHeightRequest;
|
||||
xview.HeightRequest = newH;
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<MarkdownView> e)
|
||||
@ -55,10 +62,14 @@ namespace BookAStar.Droid
|
||||
{
|
||||
// Subscribe
|
||||
editorTemplate.Model = new Markdown.MarkdownViewModel
|
||||
{ Content = e.NewElement.Markdown, Editable = e.NewElement.Editable };
|
||||
{
|
||||
Content = e.NewElement.Markdown, Editable = e.NewElement.Editable
|
||||
};
|
||||
var html = editorTemplate.GenerateString();
|
||||
EditorView.LoadDataWithBaseURL("file:///android_asset/",
|
||||
html, "text/html", "utf-8", null);
|
||||
EditorView.SetBackgroundColor(e.NewElement.BackgroundColor.ToAndroid());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +80,7 @@ namespace BookAStar.Droid
|
||||
Control.LoadUrl(string.Format("javascript: {0}", script));
|
||||
}
|
||||
}
|
||||
|
||||
MDContextMenu contextMenu;
|
||||
private WebView CreateNativeControl()
|
||||
{
|
||||
editorView = new WebView(Context);
|
||||
@ -89,9 +100,18 @@ namespace BookAStar.Droid
|
||||
EditorView.Settings.DomStorageEnabled = true;
|
||||
EditorView.AddJavascriptInterface(new JsBridgeMarkdown(this), "jsBridge");
|
||||
EditorView.ViewTreeObserver.PreDraw += ViewTreeObserver_PreDraw;
|
||||
//var app = Resolver.Resolve<IXFormsApp>() as IXFormsApp<XFormsCompatApplicationDroid>;
|
||||
//contextMenu = new MDContextMenu(app.AppContext);
|
||||
//EditorView.SetOnCreateContextMenuListener(contextMenu);
|
||||
|
||||
return EditorView;
|
||||
}
|
||||
|
||||
private void EditorView_Touch(object sender, TouchEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void ViewTreeObserver_PreDraw(object sender, ViewTreeObserver.PreDrawEventArgs e)
|
||||
{
|
||||
AdjustHeightRequest(Element, Control);
|
||||
|
@ -368,7 +368,7 @@ public class YaOAuth2Authenticator : WebRedirectAuthenticator
|
||||
var query = queryValues.FormEncode();
|
||||
|
||||
var req = WebRequest.Create(accessTokenUrl);
|
||||
// (req as HttpWebRequest).Accept = "application/json";
|
||||
(req as HttpWebRequest).Accept = "application/json";
|
||||
req.Method = "POST";
|
||||
var body = Encoding.UTF8.GetBytes(query);
|
||||
req.ContentLength = body.Length;
|
||||
|
@ -30,6 +30,12 @@
|
||||
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service android:name="fr.pschneider.bas.AccountChooserService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" />
|
||||
</service>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAVE_LOCK" />
|
||||
|
@ -200,7 +200,7 @@ namespace BookAStar.Rendering
|
||||
var uriImageLoader = imagesource as UriImageSource;
|
||||
if (uriImageLoader != null && uriImageLoader.Uri != null)
|
||||
{
|
||||
using (var client = UserHelpers.CreateClient())
|
||||
using (var client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
using (var response = await client.GetAsync(uriImageLoader.Uri))
|
||||
{
|
||||
|
3864
BookAStar/BookAStar.Droid/Resources/Resource.Designer.cs
generated
3864
BookAStar/BookAStar.Droid/Resources/Resource.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -8,4 +8,4 @@
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:tabIndicatorColor="@android:color/white"
|
||||
app:tabGravity="fill"
|
||||
app:tabMode="fixed" />
|
||||
app:tabMode="fixed" />
|
@ -7,7 +7,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
android:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
|
||||
tools:context=".MainActivity"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
/>
|
33
BookAStar/BookAStar.Droid/Resources/menu/md_menu.axml
Normal file
33
BookAStar/BookAStar.Droid/Resources/menu/md_menu.axml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/copy"
|
||||
android:title="@string/copy"/>
|
||||
<group android:id="@+id/group">
|
||||
<item android:id="@+id/past"
|
||||
android:title="@string/past"
|
||||
android:showAsAction="ifRoom|withText"/>
|
||||
</group>
|
||||
<item android:id="@+id/submenu_character"
|
||||
android:title="@string/character" >
|
||||
<menu>
|
||||
<item android:id="@+id/bold"
|
||||
android:title="@string/bold" />
|
||||
<item android:id="@+id/italic"
|
||||
android:title="@string/italic" />
|
||||
<item android:id="@+id/underline"
|
||||
android:title="@string/underline" />
|
||||
</menu>
|
||||
</item>
|
||||
<item android:id="@+id/submenu_paragraph"
|
||||
android:title="@string/paragraph" >
|
||||
<menu>
|
||||
|
||||
<item android:id="@+id/header1"
|
||||
android:onClick="onGroupItemClick"
|
||||
android:title="@string/header1" />
|
||||
<item android:id="@+id/header2"
|
||||
android:onClick="onGroupItemClick"
|
||||
android:title="@string/header2" />
|
||||
</menu>
|
||||
</item>
|
||||
</menu>
|
@ -14,5 +14,25 @@
|
||||
<string name="url">url</string>
|
||||
<string name="url_hint">url_hint</string>
|
||||
<string name="picture">picture</string>
|
||||
<string name="google_app_id">325408689282</string>
|
||||
<string name="google_app_id">325408689282</string>
|
||||
<string name="pref_screen_title">Comptes Booking Star</string>
|
||||
<string name="account_authenticator_label">Comptes Booking Star</string>
|
||||
|
||||
<string name="copy">Copier</string>
|
||||
<string name="past">Coller</string>
|
||||
|
||||
<string name="character">Caractère</string>
|
||||
<string name="bold">Gras</string>
|
||||
<string name="italic">Italique</string>
|
||||
<string name="underline">Sousligné</string>
|
||||
|
||||
<string name="paragraph">Paragraphe</string>
|
||||
<string name="header1">Titre</string>
|
||||
<string name="header2">Sous-titre</string>
|
||||
|
||||
|
||||
<string name="accounts">Comptes</string>
|
||||
<string name="bookingstar_accounts_pref_screen_summary">
|
||||
Préférences des comptes Booking Star
|
||||
</string>
|
||||
</resources>
|
||||
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory android:title="@string/accounts" />
|
||||
<PreferenceScreen
|
||||
android:key="bookingstar_accounts_pref_screen"
|
||||
android:title="@string/pref_screen_title"
|
||||
android:summary="@string/bookingstar_accounts_pref_screen_summary">
|
||||
<intent
|
||||
android:action="bookingstar_accounts_pref_screen.ACTION"
|
||||
android:targetPackage="bookingstar_accounts_pref_screen.package"
|
||||
android:targetClass="bookingstar_accounts_pref_screen.class" />
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accountType="typeOfAuthenticator"
|
||||
android:icon="@drawable/icon"
|
||||
android:smallIcon="@drawable/icon"
|
||||
android:label="@string/account_authenticator_label"
|
||||
android:accountPreferences="@xml/account_preferences"
|
||||
/>
|
41
BookAStar/BookAStar.Droid/Services/AccountChooserService.cs
Normal file
41
BookAStar/BookAStar.Droid/Services/AccountChooserService.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using BookAStar.Droid.OAuth;
|
||||
|
||||
namespace BookAStar.Droid.Services
|
||||
{
|
||||
[Service(
|
||||
Name = "fr.pschneider.bas.AccountChooserService",
|
||||
Label = "Yavsc accounts service",
|
||||
Icon = "@drawable/icon",
|
||||
Exported = true,
|
||||
Enabled = true
|
||||
)]
|
||||
[IntentFilter(new String[] { "android.accounts.AccountAuthenticator" })]
|
||||
|
||||
class AccountChooserService : Service
|
||||
{
|
||||
public static YaOAuth2Authenticator authenticator;
|
||||
public override void OnCreate()
|
||||
{
|
||||
base.OnCreate();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override IBinder OnBind(Intent intent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,9 @@ namespace BookAStar.Droid.Services
|
||||
using Model.Social;
|
||||
using Newtonsoft.Json;
|
||||
using Model;
|
||||
using Model.Social;
|
||||
using Data;
|
||||
using System.Linq;
|
||||
|
||||
namespace ClientApp
|
||||
{
|
||||
@ -44,18 +47,27 @@ namespace BookAStar.Droid.Services
|
||||
if (topic == "BookQuery")
|
||||
{
|
||||
DateTime eventdate;
|
||||
|
||||
var sdatestr = data.GetString("EventDate");
|
||||
DateTime.TryParse(sdatestr, out eventdate);
|
||||
|
||||
var locationJson = data.GetString("Location");
|
||||
var location = JsonConvert.DeserializeObject<Location>(locationJson);
|
||||
var cid = long.Parse(data.GetString("Id"));
|
||||
var bq = new BookQueryData
|
||||
var clientJson = data.GetString("Client");
|
||||
var client = JsonConvert.DeserializeObject<ClientProviderInfo>(clientJson);
|
||||
var bq = new BookQuery
|
||||
{
|
||||
Id = cid,
|
||||
Location = location
|
||||
Location = location,
|
||||
Client = client,
|
||||
Reason = data.GetString("Reason")
|
||||
};
|
||||
var dateString = data.GetString("EventDate");
|
||||
DateTime evDate;
|
||||
if (DateTime.TryParse(dateString, out evDate))
|
||||
{
|
||||
bq.EventDate = evDate;
|
||||
}
|
||||
|
||||
SendBookQueryNotification(bq);
|
||||
}
|
||||
@ -82,14 +94,17 @@ namespace BookAStar.Droid.Services
|
||||
notificationManager.Notify(0, notificationBuilder.Build());
|
||||
}
|
||||
|
||||
void SendBookQueryNotification(BookQueryData bquery)
|
||||
void SendBookQueryNotification(BookQuery bquery)
|
||||
{
|
||||
var bookquerynotifications = MainSettings.AddBookQueryNotification(bquery);
|
||||
DataManager.Instance.BookQueries.Merge(bquery);
|
||||
var bookquerynotifications = DataManager.Instance.BookQueries.Where(
|
||||
q=> ! q.Read && q.EventDate > DateTime.Now
|
||||
).ToArray();
|
||||
var count = bookquerynotifications.Length;
|
||||
var multiple = count > 1;
|
||||
var title =
|
||||
multiple ? $"{count} demandes" : bquery.Client.UserName;
|
||||
var message = $"{bquery.EventDate} {bquery.Client.UserName} {bquery.Location.Address}";
|
||||
var message = $"{bquery.EventDate} {bquery.Client.UserName} {bquery.Location.Address}\n {bquery.Reason}";
|
||||
|
||||
var intent = new Intent(this, typeof(MainActivity));
|
||||
intent.AddFlags(ActivityFlags.ClearTop);
|
||||
|
@ -7,7 +7,6 @@ using Android.Widget;
|
||||
|
||||
namespace BookAStar.Droid
|
||||
{
|
||||
|
||||
[Service]
|
||||
public class MyGcmIntentService : IntentService
|
||||
{
|
||||
@ -31,6 +30,7 @@ namespace BookAStar.Droid
|
||||
intent.SetClass(context, typeof(MyGcmIntentService));
|
||||
context.StartService(intent);
|
||||
}
|
||||
|
||||
static object locker = new object();
|
||||
|
||||
protected override void OnHandleIntent(Intent intent)
|
||||
@ -74,16 +74,28 @@ namespace BookAStar.Droid
|
||||
|
||||
void SendNotification (string message)
|
||||
{
|
||||
var intent = new Intent (this, typeof(MainActivity));
|
||||
/* Bundle valuesForActivity = new Bundle();
|
||||
valuesForActivity.PutInt("count", count); */
|
||||
|
||||
var intent = new Intent (this, typeof(MainActivity));
|
||||
intent.AddFlags (ActivityFlags.ClearTop);
|
||||
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
|
||||
// Construct a back stack for cross-task navigation:
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
|
||||
stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(MainActivity)));
|
||||
stackBuilder.AddNextIntent(intent);
|
||||
|
||||
var notificationBuilder = new Notification.Builder(this)
|
||||
// Create the PendingIntent with the back stack:
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
|
||||
|
||||
var notificationBuilder = new Notification.Builder(this)
|
||||
.SetAutoCancel(true)
|
||||
.SetSmallIcon (Resource.Drawable.icon)
|
||||
.SetContentTitle ("GCM Message")
|
||||
.SetContentText (message)
|
||||
.SetAutoCancel (true)
|
||||
.SetContentIntent (pendingIntent);
|
||||
.SetContentIntent(resultPendingIntent) // Start 2nd activity when the intent is clicked.
|
||||
;
|
||||
|
||||
var notificationManager = (NotificationManager) GetSystemService(Context.NotificationService);
|
||||
notificationManager.Notify (0, notificationBuilder.Build());
|
||||
|
@ -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>
|
||||
|
@ -9,23 +9,31 @@
|
||||
<ResourceDictionary>
|
||||
|
||||
<Color x:Key="PageBackgroundColor">#FFAAAAFF</Color>
|
||||
<Color x:Key="ContentBackgroundColor">#80AFAFAF</Color>
|
||||
<Color x:Key="DashboardPageBackgroundColor">#FFCCCCFF</Color>
|
||||
|
||||
<Color x:Key="ContentBackgroundColor">#80FFFFFF</Color>
|
||||
<Color x:Key="BackgroundColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="LabelBackgroundColor">#FFFFFFFF</Color>
|
||||
|
||||
<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>
|
||||
<Color x:Key="OddColor">#207AFAFA</Color>
|
||||
<Color x:Key="EmphasisTextColor">#800080</Color>
|
||||
<Color x:Key="QuietTextColor">#404040</Color>
|
||||
<Color x:Key="DisconnectedUserBgColor">#909090</Color>
|
||||
<Color x:Key="ConnectedUserBgColor">#ffffff</Color>
|
||||
|
||||
|
||||
<OnPlatform x:TypeArguments="Font" Android="Large" iOS="Large" WinPhone="Large" x:Key="HeaderFont" />
|
||||
<OnPlatform x:TypeArguments="Color" Android="Red" iOS="Red" WinPhone="Red" x:Key="EmphasisTextColor" />
|
||||
<OnPlatform x:TypeArguments="Font" Android="90" iOS="90" WinPhone="90" x:Key="LargeFontSize" />
|
||||
<OnPlatform x:TypeArguments="Font" Android="50" iOS="50" WinPhone="50" x:Key="MediumFontSize" />
|
||||
<OnPlatform x:TypeArguments="Font" Android="40" iOS="40" WinPhone="40" x:Key="SmallFontSize" />
|
||||
<OnPlatform x:TypeArguments="x:Double" Android="22" iOS="22" WinPhone="22" x:Key="LargeFontSize" />
|
||||
<OnPlatform x:TypeArguments="x:Double" Android="16" iOS="16" WinPhone="16" x:Key="MediumFontSize" />
|
||||
<OnPlatform x:TypeArguments="x:Double" Android="14" iOS="14" WinPhone="14" x:Key="SmallFontSize" />
|
||||
<OnPlatform x:TypeArguments="x:Double" Android="130" iOS="130" WinPhone="130" x:Key="BigUserAvatarSize" />
|
||||
|
||||
<Style x:Key="LabelPageHeadingStyle" TargetType="Label">
|
||||
@ -43,12 +51,19 @@
|
||||
<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">
|
||||
<Style x:Key="BigLabelStyle" BasedOn="{StaticResource LabelStyle}" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="Large" />
|
||||
</Style>
|
||||
<Style x:Key="ContentLabelStyle" BasedOn="{StaticResource LabelStyle}" TargetType="Label">
|
||||
@ -80,11 +95,14 @@
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PageStyle" TargetType="ContentPage">
|
||||
<Setter Property="Padding" Value="5,5,5,5" />
|
||||
<Setter Property="Padding" Value="15,15,15,15" />
|
||||
<Setter Property="BackgroundColor" Value="{StaticResource PageBackgroundColor}" />
|
||||
</Style>
|
||||
|
||||
|
||||
<Style x:Key="DashboardPageStyle" TargetType="ContentPage">
|
||||
<Setter Property="Padding" Value="10,10,10,10" />
|
||||
<Setter Property="BackgroundColor" Value="{StaticResource DashboardPageBackgroundColor}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
@ -19,7 +19,6 @@ namespace BookAStar
|
||||
using Data;
|
||||
using Interfaces;
|
||||
using Model;
|
||||
using Model.UI;
|
||||
using Pages;
|
||||
using Plugin.Connectivity;
|
||||
using Model.Social.Messaging;
|
||||
@ -27,6 +26,11 @@ namespace BookAStar
|
||||
using ViewModels.UserProfile;
|
||||
using Pages.UserProfile;
|
||||
using ViewModels.EstimateAndBilling;
|
||||
using Pages.EstimatePages;
|
||||
using ViewModels;
|
||||
using Pages.Chat;
|
||||
using System.Collections.Generic;
|
||||
using Model.Social;
|
||||
|
||||
public partial class App : Application // superclass new in 1.3
|
||||
{
|
||||
@ -35,13 +39,14 @@ namespace BookAStar
|
||||
|
||||
[Obsolete("Instead using this, use new static properties.")]
|
||||
public static App CurrentApp { get { return Current as App; } }
|
||||
|
||||
|
||||
private static ExtendedMasterDetailPage masterDetail;
|
||||
public static bool MasterPresented
|
||||
{
|
||||
get
|
||||
{ return CurrentApp.masterDetail.IsPresented; }
|
||||
{ return App.masterDetail.IsPresented; }
|
||||
internal set
|
||||
{ CurrentApp.masterDetail.IsPresented = value; }
|
||||
{ masterDetail.IsPresented = value; }
|
||||
}
|
||||
|
||||
public void Init()
|
||||
@ -63,27 +68,27 @@ namespace BookAStar
|
||||
MainSettings.UserChanged += MainSettings_UserChanged;
|
||||
CrossConnectivity.Current.ConnectivityChanged += (conSender, args) =>
|
||||
{ App.IsConnected = args.IsConnected; };
|
||||
SetupHubConnection();
|
||||
MainSettings_UserChanged(this, null);
|
||||
if (CrossConnectivity.Current.IsConnected)
|
||||
StartHubConnection();
|
||||
|
||||
StartConnexion();
|
||||
}
|
||||
|
||||
// omg
|
||||
private void OnError(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Called on rotation after OnSuspended
|
||||
private void OnClosing(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// FIXME Never called.
|
||||
private void OnInitialize(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
// called on app startup, not on rotation
|
||||
@ -92,17 +97,22 @@ namespace BookAStar
|
||||
// TODO special startup pages as
|
||||
// notification details or wizard setup page
|
||||
}
|
||||
|
||||
private static INavigation Navigation
|
||||
{
|
||||
get
|
||||
{
|
||||
return masterDetail.Detail.Navigation;
|
||||
}
|
||||
}
|
||||
// Called on rotation
|
||||
private void OnSuspended(object sender, EventArgs e)
|
||||
{
|
||||
// TODO save the navigation stack
|
||||
StopConnection();
|
||||
int position = 0;
|
||||
|
||||
foreach (Page page in MainPage.Navigation.NavigationStack)
|
||||
DataManager.Instance.AppState.Clear();
|
||||
foreach (Page page in Navigation.NavigationStack)
|
||||
{
|
||||
|
||||
DataManager.Current.AppState.Add(
|
||||
DataManager.Instance.AppState.Add(
|
||||
new PageState
|
||||
{
|
||||
Position = position++,
|
||||
@ -110,28 +120,35 @@ namespace BookAStar
|
||||
BindingContext = page.BindingContext
|
||||
});
|
||||
}
|
||||
DataManager.Current.AppState.SaveEntity();
|
||||
DataManager.Instance.AppState.SaveEntity();
|
||||
}
|
||||
|
||||
// called on app startup, after OnStartup, not on rotation
|
||||
private void OnAppResumed(object sender, EventArgs e)
|
||||
{
|
||||
StartConnexion();
|
||||
// TODO restore the navigation stack
|
||||
base.OnResume();
|
||||
foreach (var pageState in DataManager.Current.AppState)
|
||||
foreach (var pageState in DataManager.Instance.AppState)
|
||||
{
|
||||
var pageType = Type.GetType(pageState.PageType);
|
||||
NavigationService.NavigateTo(
|
||||
pageType, true, pageState.BindingContext);
|
||||
if (pageState.PageType != null)
|
||||
{
|
||||
var pageType = Type.GetType(pageState.PageType);
|
||||
if (pageState.BindingContext != null)
|
||||
NavigationService.NavigateTo(
|
||||
pageType, false, pageState.BindingContext);
|
||||
else NavigationService.NavigateTo(
|
||||
pageType, false);
|
||||
}
|
||||
}
|
||||
DataManager.Current.AppState.Clear();
|
||||
DataManager.Current.AppState.SaveEntity();
|
||||
DataManager.Instance.AppState.Clear();
|
||||
DataManager.Instance.AppState.SaveEntity();
|
||||
}
|
||||
|
||||
// FIXME Not called?
|
||||
private void OnRotation(object sender, EventArgs<Orientation> e)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static GenericConfigSettingsMgr ConfigManager { protected set; get; }
|
||||
@ -139,9 +156,6 @@ namespace BookAStar
|
||||
private void Configure(IXFormsApp app)
|
||||
{
|
||||
ViewFactory.EnableCache = true;
|
||||
ViewFactory.Register<ChatPage, ChatViewModel>(
|
||||
r=> new ChatViewModel { ChatUser = MainSettings.UserName }
|
||||
);
|
||||
ViewFactory.Register<DashboardPage, DashboardViewModel>(
|
||||
resolver => new DashboardViewModel());
|
||||
ViewFactory.Register<BookQueryPage, BookQueryViewModel>();
|
||||
@ -150,12 +164,11 @@ namespace BookAStar
|
||||
ViewFactory.Register<EditEstimatePage, EditEstimateViewModel>();
|
||||
ViewFactory.Register<UserFiles, DirectoryInfoViewModel>();
|
||||
ViewFactory.Register<UserProfilePage, UserProfileViewModel>();
|
||||
ViewFactory.Register<EstimateSigningPage, EditEstimateViewModel>();
|
||||
ConfigManager = new GenericConfigSettingsMgr(s =>
|
||||
MainSettings.AppSettings.GetValueOrDefault<string>(s, MainSettings.SettingsDefault), null);
|
||||
}
|
||||
|
||||
ExtendedMasterDetailPage masterDetail;
|
||||
|
||||
public App(IPlatform instance)
|
||||
{
|
||||
// This declaration became obsolete by introduction
|
||||
@ -170,39 +183,64 @@ namespace BookAStar
|
||||
Init();
|
||||
// Builds the Main page
|
||||
BuildMainPage();
|
||||
|
||||
|
||||
}
|
||||
|
||||
BookQueriesPage bQueriesPage;
|
||||
AccountChooserPage accChooserPage;
|
||||
HomePage homePage;
|
||||
UserProfilePage userProfilePage;
|
||||
|
||||
private static UserProfilePage userProfilePage;
|
||||
|
||||
public static UserProfilePage UserProfilePage
|
||||
{ get { return userProfilePage; } }
|
||||
|
||||
ChatPage chatPage;
|
||||
|
||||
private void ShowPage(Page page)
|
||||
public static void ShowPage(Page page)
|
||||
{
|
||||
if (masterDetail.Detail.Navigation.NavigationStack.Contains(page))
|
||||
if (Navigation.NavigationStack.Contains(page))
|
||||
{
|
||||
if (masterDetail.Detail.Navigation.NavigationStack.Last() == page) return;
|
||||
masterDetail.Detail.Navigation.RemovePage(page);
|
||||
if (Navigation.NavigationStack.Last() == page) return;
|
||||
Navigation.RemovePage(page);
|
||||
page.Parent = null;
|
||||
}
|
||||
masterDetail.Detail.Navigation.PushAsync(page);
|
||||
Navigation.PushAsync(page);
|
||||
}
|
||||
|
||||
private void BuildMainPage()
|
||||
{
|
||||
// TODO
|
||||
// in case of App resume,
|
||||
// do not create new BindingContext's,
|
||||
// but use those from the AppState property
|
||||
accChooserPage = new AccountChooserPage();
|
||||
|
||||
var bookQueries = new BookQueriesViewModel();
|
||||
|
||||
var userprofile = new UserProfileViewModel();
|
||||
|
||||
bQueriesPage = new BookQueriesPage
|
||||
{
|
||||
Title = "Demandes",
|
||||
Icon = "icon.png",
|
||||
BindingContext = new BookQueriesViewModel()
|
||||
BindingContext = bookQueries
|
||||
};
|
||||
homePage = new HomePage() { Title = "Accueil", Icon = "icon.png" };
|
||||
userProfilePage = new UserProfilePage { Title = "Profile utilisateur", Icon = "ic_corp_icon.png",
|
||||
BindingContext = new UserProfileViewModel() };
|
||||
|
||||
homePage = new HomePage() {
|
||||
Title = "Accueil",
|
||||
Icon = "icon.png" };
|
||||
|
||||
homePage.BindingContext = new HomeViewModel {
|
||||
BookQueries = bookQueries,
|
||||
UserProfile = userprofile };
|
||||
|
||||
userProfilePage = new UserProfilePage {
|
||||
Title = "Profile utilisateur",
|
||||
Icon = "ic_corp_icon.png",
|
||||
BindingContext = userprofile
|
||||
};
|
||||
|
||||
chatPage = new ChatPage
|
||||
{
|
||||
Title = "Chat",
|
||||
@ -259,11 +297,11 @@ namespace BookAStar
|
||||
masterDetail.ToolbarItems.Add(tiPubChat);
|
||||
this.MainPage = masterDetail;
|
||||
|
||||
NavigationService = new NavigationService(masterDetail.Detail.Navigation);
|
||||
NavigationService = new NavigationService(Navigation);
|
||||
}
|
||||
public static Task<string> DisplayActionSheet(string title, string cancel, string destruction, string [] buttons)
|
||||
{
|
||||
var currentPage = CurrentApp.masterDetail.Detail.Navigation.NavigationStack.Last();
|
||||
var currentPage = Navigation.NavigationStack.Last();
|
||||
return currentPage.DisplayActionSheet(title, cancel, destruction, buttons);
|
||||
}
|
||||
|
||||
@ -293,7 +331,7 @@ namespace BookAStar
|
||||
if (isConnected)
|
||||
{
|
||||
// TODO Start all cloud related stuff
|
||||
CurrentApp.StartHubConnection();
|
||||
StartConnexion();
|
||||
}
|
||||
|
||||
}
|
||||
@ -308,18 +346,20 @@ namespace BookAStar
|
||||
}
|
||||
}
|
||||
// Start the Hub connection
|
||||
public async void StartHubConnection ()
|
||||
public static async void StartConnexion ()
|
||||
{
|
||||
try
|
||||
if (CrossConnectivity.Current.IsConnected)
|
||||
try
|
||||
{
|
||||
if (chatHubConnection.State == ConnectionState.Disconnected)
|
||||
await chatHubConnection.Start();
|
||||
}
|
||||
catch (WebException webex )
|
||||
catch (WebException )
|
||||
{
|
||||
// TODO use webex, set this cx down status somewhere,
|
||||
// & display it & maybe try again later.
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception )
|
||||
{
|
||||
// TODO use ex
|
||||
}
|
||||
@ -327,36 +367,53 @@ namespace BookAStar
|
||||
|
||||
public void SetupHubConnection()
|
||||
{
|
||||
if (chatHubConnection != null)
|
||||
chatHubConnection.Dispose();
|
||||
chatHubConnection = new HubConnection(Constants.SignalRHubsUrl);
|
||||
chatHubConnection.Error += ChatHubConnection_Error;
|
||||
|
||||
chatHubProxy = chatHubConnection.CreateHubProxy("ChatHub");
|
||||
chatHubProxy.On<string, string>("addPV", (n, m) => {
|
||||
DataManager.Current.PrivateMessages.Add(
|
||||
new ChatMessage
|
||||
{
|
||||
Message = m,
|
||||
SenderId = n,
|
||||
Date = DateTime.Now
|
||||
}
|
||||
var msg = new ChatMessage
|
||||
{
|
||||
Message = m,
|
||||
SenderId = n,
|
||||
Date = DateTime.Now
|
||||
};
|
||||
DataManager.Instance.PrivateMessages.Add(
|
||||
msg
|
||||
);
|
||||
DataManager.Instance.ChatUsers.OnPrivateMessage(msg);
|
||||
});
|
||||
}
|
||||
|
||||
public static void StopConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (chatHubConnection.State != ConnectionState.Disconnected)
|
||||
chatHubConnection.Stop();
|
||||
}
|
||||
catch (WebException)
|
||||
{
|
||||
// TODO use webex, set this cx down status somewhere,
|
||||
// & display it & maybe try again later.
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// TODO use ex
|
||||
}
|
||||
}
|
||||
private void MainSettings_UserChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (MainSettings.CurrentUser == null)
|
||||
{
|
||||
chatHubConnection.Dispose();
|
||||
chatHubConnection = null;
|
||||
chatHubProxy = null;
|
||||
}
|
||||
else
|
||||
StopConnection();
|
||||
if (MainSettings.CurrentUser != null)
|
||||
{
|
||||
var token = MainSettings.CurrentUser.YavscTokens.AccessToken;
|
||||
SetupHubConnection();
|
||||
if (chatHubConnection.Headers.ContainsKey("Authorization"))
|
||||
chatHubConnection.Headers.Remove("Authorization");
|
||||
chatHubConnection.Headers.Add("Authorization", $"Bearer {token}");
|
||||
}
|
||||
StartConnexion();
|
||||
}
|
||||
|
||||
private void ChatHubConnection_Error(Exception obj)
|
||||
@ -379,18 +436,18 @@ namespace BookAStar
|
||||
}
|
||||
}
|
||||
|
||||
public void PostDeviceInfo()
|
||||
public static void PostDeviceInfo()
|
||||
{
|
||||
var info = PlatformSpecificInstance.GetDeviceInfo();
|
||||
if (!string.IsNullOrWhiteSpace(info.GCMRegistrationId))
|
||||
PlatformSpecificInstance.InvokeApi("gcm/register", info);
|
||||
}
|
||||
|
||||
public static void ShowBookQuery (BookQueryData query)
|
||||
public static void ShowBookQuery (BookQuery query)
|
||||
{
|
||||
var page = ViewFactory.CreatePage<BookQueryViewModel
|
||||
, BookQueryPage>((b, p) => p.BindingContext = new BookQueryViewModel(query));
|
||||
App.Current.MainPage.Navigation.PushAsync(page as Page);
|
||||
var page = new BookQueryPage
|
||||
{ BindingContext = new BookQueryViewModel(query) };
|
||||
ShowPage(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -42,23 +42,43 @@
|
||||
</Compile>
|
||||
<Compile Include="Attributes\CurrencyAttribute.cs" />
|
||||
<Compile Include="Attributes\DisplayAttribute.cs" />
|
||||
<Compile Include="Behaviors\EmailValidatorBehavior.cs" />
|
||||
<Compile Include="Behaviors\IntegerEntryBehavior.cs" />
|
||||
<Compile Include="Behaviors\MaxLengthValidator.cs" />
|
||||
<Compile Include="Behaviors\DecimalValidatorBehavior.cs" />
|
||||
<Compile Include="Behaviors\PickerBehavior.cs" />
|
||||
<Compile Include="Behaviors\StarBehavior.cs" />
|
||||
<Compile Include="Converters\Behaviors\EmailValidatorBehavior.cs" />
|
||||
<Compile Include="Converters\Behaviors\IntegerEntryBehavior.cs" />
|
||||
<Compile Include="Converters\Behaviors\EditorMaxLengthValidator.cs" />
|
||||
<Compile Include="Converters\Behaviors\DecimalValidatorBehavior.cs" />
|
||||
<Compile Include="Converters\Behaviors\MarkdownViewLengthValidator.cs" />
|
||||
<Compile Include="Converters\Behaviors\PickerBehavior.cs" />
|
||||
<Compile Include="Converters\Behaviors\RegexValidatorBehavior.cs" />
|
||||
<Compile Include="Converters\Behaviors\StarBehavior.cs" />
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="Converters\NotValueConverter.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="Model\Access\BlackListed.cs" />
|
||||
<Compile Include="Model\Booking\MusicalPreference.cs" />
|
||||
<Compile Include="Model\Booking\MusicalTendency.cs" />
|
||||
<Compile Include="Model\FileSystem\UserDirectoryInfo.cs" />
|
||||
<Compile Include="Model\FileSystem\UserFileInfo.cs" />
|
||||
<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="Model\Social\Chat\ChatStatus.cs" />
|
||||
<Compile Include="Model\Social\Chat\ChatMessage.cs" />
|
||||
<Compile Include="Model\Social\LocationType.cs" />
|
||||
<Compile Include="Pages\ClientPages\SearchPage.xaml.cs">
|
||||
<DependentUpon>SearchPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ViewModels\HomeViewModel.cs" />
|
||||
<Compile Include="ViewModels\Messaging\ChatUserCollection.cs" />
|
||||
<Compile Include="ViewModels\Messaging\ChatUserInfo.cs" />
|
||||
<Compile Include="Model\Social\Chat\Connection.cs" />
|
||||
<Compile Include="ViewModels\Searching\SearchingAnArtistViewModel.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>
|
||||
<Compile Include="Pages\EstimatePages\EstimatesClientPage.xaml.cs">
|
||||
<DependentUpon>EstimatesClientPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -85,14 +105,15 @@
|
||||
<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>
|
||||
<Compile Include="ViewModels\Signing\DocSigningViewModel.cs" />
|
||||
<Compile Include="ViewModels\Signing\EstimateSigningViewModel.cs" />
|
||||
<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" />
|
||||
@ -126,7 +147,7 @@
|
||||
<Compile Include="Pages\EstimatePages\BookQueryPage.xaml.cs">
|
||||
<DependentUpon>BookQueryPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\ChatPage.xaml.cs">
|
||||
<Compile Include="Pages\Chat\ChatPage.xaml.cs">
|
||||
<DependentUpon>ChatPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\EstimatePages\EditBillingLinePage.xaml.cs">
|
||||
@ -143,7 +164,7 @@
|
||||
<Compile Include="Interfaces\IPlatform.cs" />
|
||||
<Compile Include="Model\Blog\Blog.cs" />
|
||||
<Compile Include="Model\Blog\BlogTag.cs" />
|
||||
<Compile Include="Model\BookQueryData.cs" />
|
||||
<Compile Include="Model\Booking\BookQuery.cs" />
|
||||
<Compile Include="Model\Market\BaseProduct.cs" />
|
||||
<Compile Include="Model\Workflow\BillingLine.cs" />
|
||||
<Compile Include="Model\Manager.cs" />
|
||||
@ -183,7 +204,7 @@
|
||||
<Compile Include="Pages\EstimatePages\EditEstimatePage.xaml.cs">
|
||||
<DependentUpon>EditEstimatePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\Oooops\HomePage.xaml.cs">
|
||||
<Compile Include="Pages\HomePage.xaml.cs">
|
||||
<DependentUpon>HomePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\Oooops\PinPage.cs" />
|
||||
@ -198,9 +219,6 @@
|
||||
<Compile Include="Views\ImageButton.cs" />
|
||||
<Compile Include="Views\MarkdownView.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Pages\Oooops\SearchPage.xaml.cs">
|
||||
<DependentUpon>SearchPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\UserProfile\AccountChooserPage.xaml.cs">
|
||||
<DependentUpon>AccountChooserPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -233,17 +251,13 @@
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Pages\Oooops\SearchPage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Pages\UserProfile\AccountChooserPage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Model\Billing\" />
|
||||
<Folder Include="Model\UI\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ExifLib, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@ -272,6 +286,12 @@
|
||||
<Reference Include="Plugin.Connectivity.Abstractions">
|
||||
<HintPath>..\..\packages\Xam.Plugin.Connectivity.2.2.12\lib\MonoAndroid10\Plugin.Connectivity.Abstractions.dll</HintPath>
|
||||
</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">
|
||||
<HintPath>..\..\packages\Xam.Plugins.Settings.2.5.1.0\lib\portable-net45+wp80+win8+wpa81\Plugin.Settings.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -296,6 +316,9 @@
|
||||
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net45+win8+wpa81\System.Net.Http.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Services">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\System.Web.Services.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xamarin.Forms.2.3.2.127\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -351,12 +374,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>
|
||||
@ -390,7 +407,7 @@
|
||||
<EmbeddedResource Include="Images\Users\icon_user_settings.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Pages\Oooops\HomePage.xaml">
|
||||
<EmbeddedResource Include="Pages\HomePage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
@ -416,7 +433,7 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Pages\ChatPage.xaml">
|
||||
<EmbeddedResource Include="Pages\Chat\ChatPage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
@ -478,6 +495,27 @@
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Pages\EstimatePages\EstimateSigningPage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\YavscLib\YavscLib.csproj">
|
||||
<Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
|
||||
<Name>YavscLib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Images\Chat\talk.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Pages\ClientPages\SearchPage.xaml">
|
||||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</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">
|
||||
|
@ -11,11 +11,13 @@ namespace BookAStar
|
||||
{
|
||||
public const string ApplicationName = "Booking Star";
|
||||
|
||||
#region Uri
|
||||
|
||||
#if DEV
|
||||
public const string YavscHomeUrl = "http://dev.pschneider.fr";
|
||||
#else
|
||||
#if WDEV
|
||||
public const string YavscHomeUrl = "http://192.168.0.29:5000";
|
||||
#else
|
||||
#if YAVSC
|
||||
public const string YavscHomeUrl = "https://yavsc.pschneider.fr";
|
||||
#else
|
||||
@ -26,17 +28,19 @@ namespace BookAStar
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
public static readonly string AuthorizeUrl = YavscHomeUrl + "/authorize";
|
||||
public static readonly string RedirectUrl = YavscHomeUrl + "/oauth/success";
|
||||
public static readonly string AccessTokenUrl = YavscHomeUrl + "/token";
|
||||
|
||||
public static readonly string YavscApiUrl = YavscHomeUrl + "/api";
|
||||
public static readonly string MobileRegistrationUrl = YavscApiUrl + "/gcm/register";
|
||||
public static readonly string UserInfoUrl = YavscApiUrl + "/me";
|
||||
public static readonly string BlogUrl = YavscApiUrl + "/blogs";
|
||||
public static readonly string FsUrl = YavscApiUrl + "/fs";
|
||||
public static readonly string SignalRHubsUrl = YavscHomeUrl + "/api/signalr/hubs";
|
||||
#endregion
|
||||
|
||||
#region Permissions ids
|
||||
public static int AllowBeATarget = 1;
|
||||
#endregion
|
||||
|
||||
public static int CloudTimeout = 400;
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
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), int.MaxValue);
|
||||
|
||||
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); }
|
||||
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 { 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
bindable.TextChanged -= bindable_TextChanged;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.Behaviors
|
||||
{
|
||||
public class EmailValidatorBehavior : RegexValidatorBehavior
|
||||
{
|
||||
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]))$";
|
||||
|
||||
public EmailValidatorBehavior()
|
||||
{
|
||||
Regexp = emailRegex;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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,21 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.Behaviors
|
||||
{
|
||||
public class EmailValidatorBehavior : Behavior<Entry>
|
||||
public class RegexValidatorBehavior : Behavior<Entry>
|
||||
{
|
||||
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]))$";
|
||||
|
||||
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(EmailValidatorBehavior), false);
|
||||
static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(RegexValidatorBehavior), false);
|
||||
|
||||
public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;
|
||||
|
||||
@ -25,6 +19,19 @@ namespace BookAStar.Behaviors
|
||||
private set { base.SetValue(IsValidPropertyKey, value); }
|
||||
}
|
||||
|
||||
protected string Regexp
|
||||
{
|
||||
get
|
||||
{
|
||||
return regexp;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
regexp = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAttachedTo(Entry bindable)
|
||||
{
|
||||
bindable.TextChanged += HandleTextChanged;
|
||||
@ -33,7 +40,7 @@ namespace BookAStar.Behaviors
|
||||
|
||||
void HandleTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
IsValid = (Regex.IsMatch(e.NewTextValue, emailRegex, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
|
||||
IsValid = (Regex.IsMatch(e.NewTextValue, regexp, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
|
||||
((Entry)sender).TextColor = IsValid ? Color.Default : Color.Red;
|
||||
}
|
||||
|
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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -3,45 +3,49 @@
|
||||
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;
|
||||
using Model.Access;
|
||||
using ViewModels.Messaging;
|
||||
using Model.Social;
|
||||
|
||||
public class DataManager
|
||||
{
|
||||
// TODO estimatetemplate rating service product tag
|
||||
public RemoteEntityRO<BookQueryData, long> BookQueries { get; set; }
|
||||
public RemoteEntity<Estimate, long> Estimates { get; set; }
|
||||
public RemoteEntityRO<BookQuery, long> BookQueries { get; set; }
|
||||
public ChatUserCollection ChatUsers { get; set; }
|
||||
public EstimateEntity Estimates { get; set; }
|
||||
public RemoteEntity<Blog, long> Blogspot { get; set; }
|
||||
internal RemoteFilesEntity RemoteFiles { get; set; }
|
||||
|
||||
public LocalEntity<ClientProviderInfo,string> Contacts { get; set; }
|
||||
internal LocalEntity<PageState, int> AppState { get; set; }
|
||||
|
||||
public LocalEntity<ClientProviderInfo, string> Contacts { get; set; }
|
||||
internal RemoteEntity<BlackListed, long> BlackList { get; set; }
|
||||
/// <summary>
|
||||
/// They have no remote exisence ...
|
||||
/// They've got no remote existence ...
|
||||
/// </summary>
|
||||
internal LocalEntity<EditEstimateViewModel, long> EstimationCache { get; set; }
|
||||
internal LocalEntity<BillingLine, string> EstimateLinesTemplates { get; set; }
|
||||
internal LocalEntity<ChatMessage, int> PrivateMessages { get; set; }
|
||||
protected static DataManager current ;
|
||||
internal LocalEntity<PageState, int> AppState { get; set; }
|
||||
internal LocalEntity<string,string> ClientSignatures { get; set; }
|
||||
internal LocalEntity<string, string> ProviderSignatures { get; set; }
|
||||
|
||||
public static DataManager Current
|
||||
protected static DataManager instance = new DataManager();
|
||||
|
||||
public static DataManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (current == null)
|
||||
current = new DataManager();
|
||||
return current;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public DataManager()
|
||||
{
|
||||
BookQueries = new RemoteEntityRO<BookQueryData, long>("bookquery", q => q.Id);
|
||||
Estimates = new RemoteEntity<Estimate, long>("estimate", x => x.Id);
|
||||
BookQueries = new RemoteEntityRO<BookQuery, long>("bookquery", q => q.Id);
|
||||
Estimates = new EstimateEntity();
|
||||
Blogspot = new RemoteEntity<Blog, long>("blog", x=>x.Id);
|
||||
|
||||
Contacts = new LocalEntity<ClientProviderInfo, string>(c => c.UserId);
|
||||
@ -50,7 +54,8 @@
|
||||
EstimateLinesTemplates = new LocalEntity<BillingLine, string>(l => l.Description);
|
||||
PrivateMessages = new LocalEntity<ChatMessage, int>(m=> m.GetHashCode());
|
||||
RemoteFiles = new RemoteFilesEntity ();
|
||||
|
||||
BlackList = new RemoteEntity<BlackListed, long>("blacklist",u => u.Id);
|
||||
ChatUsers = new ChatUserCollection();
|
||||
PrivateMessages.Load();
|
||||
BookQueries.Load();
|
||||
Estimates.Load();
|
||||
@ -60,6 +65,9 @@
|
||||
EstimationCache.Load();
|
||||
EstimateLinesTemplates.Load();
|
||||
RemoteFiles.Load();
|
||||
BlackList.Load();
|
||||
ChatUsers.Load();
|
||||
BlackList.Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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.CreateJsonClient())
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -6,13 +6,6 @@ namespace BookAStar.Data.NonCrUD
|
||||
{
|
||||
using Helpers;
|
||||
using Model.FileSystem;
|
||||
using System.Linq;
|
||||
/*
|
||||
public class DirectoryEntryChangingEvent : EventArgs
|
||||
{
|
||||
public UserDirectoryInfo OldItem { get; set; }
|
||||
public UserDirectoryInfo NewItem { get; set; }
|
||||
}*/
|
||||
|
||||
public class RemoteFilesEntity : RemoteEntity<UserDirectoryInfo, FileAddress>
|
||||
{
|
||||
@ -24,7 +17,7 @@ namespace BookAStar.Data.NonCrUD
|
||||
public override async void Execute(object parameter)
|
||||
{
|
||||
BeforeExecute();
|
||||
using (var client = UserHelpers.CreateClient())
|
||||
using (var client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
// Get the whole data
|
||||
try
|
||||
|
@ -11,6 +11,7 @@ namespace BookAStar.Data
|
||||
using Helpers;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
public class RemoteEntity<V, K> : LocalEntity<V, K>, ICommand where K : IEquatable<K>
|
||||
{
|
||||
@ -22,7 +23,7 @@ namespace BookAStar.Data
|
||||
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
return !IsExecuting && (MainSettings.CurrentUser != null);
|
||||
return !IsExecuting;
|
||||
}
|
||||
|
||||
public RemoteEntity(string controllerName, Func<V, K> getKey) : base(getKey)
|
||||
@ -36,7 +37,7 @@ namespace BookAStar.Data
|
||||
protected void BeforeExecute()
|
||||
{
|
||||
if (IsExecuting)
|
||||
throw new InvalidOperationException("Already executing");
|
||||
throw new InvalidOperationException(Strings.AlreadyExecuting);
|
||||
IsExecuting = true;
|
||||
if (CanExecuteChanged != null)
|
||||
CanExecuteChanged.Invoke(this, new EventArgs());
|
||||
@ -49,7 +50,7 @@ namespace BookAStar.Data
|
||||
public virtual async void Execute(object parameter)
|
||||
{
|
||||
BeforeExecute();
|
||||
using (HttpClient client = UserHelpers.CreateClient())
|
||||
using (HttpClient client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
// Get the whole data
|
||||
try
|
||||
@ -71,7 +72,7 @@ namespace BookAStar.Data
|
||||
}
|
||||
catch (WebException webex)
|
||||
{
|
||||
throw new ServiceNotAvailable("No remote entity", webex);
|
||||
throw new ServiceNotAvailable(Strings.ENoRemoteEntity, webex);
|
||||
}
|
||||
|
||||
}
|
||||
@ -95,7 +96,7 @@ namespace BookAStar.Data
|
||||
|
||||
protected Uri GetUri(K key)
|
||||
{
|
||||
return new Uri(ControllerUri.AbsoluteUri + "/" + key.ToString());
|
||||
return new Uri(ControllerUri.AbsoluteUri + "/" + HttpUtility.UrlEncode(key.ToString()));
|
||||
}
|
||||
|
||||
public virtual async Task<V> RemoteGet(K key)
|
||||
@ -105,7 +106,7 @@ namespace BookAStar.Data
|
||||
// Get the whole data
|
||||
var uri = GetUri(key);
|
||||
|
||||
using (HttpClient client = UserHelpers.CreateClient())
|
||||
using (HttpClient client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
using (var response = await client.GetAsync(uri))
|
||||
{
|
||||
@ -123,23 +124,27 @@ namespace BookAStar.Data
|
||||
return item;
|
||||
}
|
||||
|
||||
public virtual async void Create(V item)
|
||||
public virtual async Task<bool> Create(V item)
|
||||
{
|
||||
bool created = false;
|
||||
BeforeExecute();
|
||||
|
||||
using (HttpClient client = UserHelpers.CreateClient())
|
||||
using (HttpClient client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
var stringContent = JsonConvert.SerializeObject(item);
|
||||
|
||||
HttpContent content = new StringContent(
|
||||
stringContent, Encoding.UTF8, "application/json"
|
||||
);
|
||||
using (var response = await client.PostAsync(ControllerUri, content))
|
||||
{
|
||||
if (!response.IsSuccessStatusCode)
|
||||
created = response.IsSuccessStatusCode;
|
||||
if (!created)
|
||||
{
|
||||
// TODO throw custom exception, and catch to inform user
|
||||
var errcontent = await response.Content.ReadAsStringAsync();
|
||||
Debug.WriteLine($"Create failed posting {stringContent} @ {ControllerUri.AbsoluteUri}: {errcontent}");
|
||||
Debug.WriteLine(string.Format(Strings.CreationFailed));
|
||||
Debug.WriteLine(errcontent);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -148,31 +153,35 @@ namespace BookAStar.Data
|
||||
JsonConvert.PopulateObject(recontent, item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CurrentItem = item;
|
||||
AfterExecuting();
|
||||
return created;
|
||||
}
|
||||
public virtual async void Update(V item)
|
||||
public virtual async Task<bool> Update(V item)
|
||||
{
|
||||
var updated = false;
|
||||
BeforeExecute();
|
||||
|
||||
var uri = GetUri(GetKey(item));
|
||||
using (HttpClient client = UserHelpers.CreateClient())
|
||||
using (HttpClient client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
HttpContent content = new StringContent(
|
||||
JsonConvert.SerializeObject(item), Encoding.UTF8, "application/json"
|
||||
);
|
||||
using (var response = await client.PutAsync(uri, content))
|
||||
{
|
||||
if (!response.IsSuccessStatusCode)
|
||||
updated = response.IsSuccessStatusCode;
|
||||
if (!updated)
|
||||
{// TODO throw custom exception, and catch to inform user
|
||||
if (response.StatusCode == HttpStatusCode.BadRequest)
|
||||
{
|
||||
var recontent = await response.Content.ReadAsStringAsync();
|
||||
var errorcontent = await response.Content.ReadAsStringAsync();
|
||||
Debug.WriteLine(string.Format(Strings.UpdateFailed));
|
||||
Debug.WriteLine(errorcontent);
|
||||
|
||||
}
|
||||
|
||||
else Debug.WriteLine($"Update failed ({item} @ {uri.AbsolutePath} )");
|
||||
|
||||
}
|
||||
@ -188,13 +197,14 @@ namespace BookAStar.Data
|
||||
|
||||
CurrentItem = item;
|
||||
AfterExecuting();
|
||||
return updated;
|
||||
}
|
||||
|
||||
public virtual async void Delete(K key)
|
||||
{
|
||||
BeforeExecute();
|
||||
var uri = GetUri(key);
|
||||
using (HttpClient client = UserHelpers.CreateClient())
|
||||
using (HttpClient client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
using (var response = await client.DeleteAsync(uri))
|
||||
{
|
||||
|
@ -17,18 +17,35 @@ namespace BookAStar.Helpers
|
||||
{
|
||||
var result = avatarPath == null ?
|
||||
ImageSource.FromResource( "BookAStar.Images.Users.icon_user.png") :
|
||||
avatarPath.StartsWith("res://") ?
|
||||
ImageSource.FromResource(avatarPath.Substring(6)) :
|
||||
ImageSource.FromUri(new Uri(avatarPath));
|
||||
ImageSource.FromUri(new Uri(Constants.YavscHomeUrl+"/Avatars/"+avatarPath)) ;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static HttpClient CreateClient()
|
||||
public static ImageSource SmallAvatar(string avatarPath, string username)
|
||||
{
|
||||
return avatarPath == null ?
|
||||
ImageSource.FromResource("BookAStar.Images.Users.icon_user.png") :
|
||||
ImageSource.FromUri(new Uri($"{Constants.YavscHomeUrl}/Avatars/{username}.s.png"));
|
||||
}
|
||||
|
||||
public static ImageSource ExtraSmallAvatar(string avatarPath, string username)
|
||||
{
|
||||
return avatarPath == null ?
|
||||
ImageSource.FromResource("BookAStar.Images.Users.icon_user.png") :
|
||||
ImageSource.FromUri(new Uri($"{Constants.YavscHomeUrl}/Avatars/{username}.xs.png"));
|
||||
}
|
||||
|
||||
public static HttpClient CreateJsonClient()
|
||||
{
|
||||
return CreateJsonClient(MainSettings.CurrentUser.YavscTokens.AccessToken);
|
||||
}
|
||||
|
||||
public static HttpClient CreateJsonClient(string accessToken)
|
||||
{
|
||||
var client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Authorization =
|
||||
new System.Net.Http.Headers.AuthenticationHeaderValue(
|
||||
"Bearer", MainSettings.CurrentUser.YavscTokens.AccessToken);
|
||||
"Bearer", accessToken);
|
||||
client.DefaultRequestHeaders.Add("Accept", "application/json");
|
||||
return client;
|
||||
}
|
||||
@ -42,7 +59,7 @@ namespace BookAStar.Helpers
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> Upload(Stream inputStream, string fileName)
|
||||
{
|
||||
using (var client = CreateClient())
|
||||
using (var client = CreateJsonClient())
|
||||
{
|
||||
using (var content =
|
||||
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
|
||||
|
BIN
BookAStar/BookAStar/Images/Chat/talk.png
Normal file
BIN
BookAStar/BookAStar/Images/Chat/talk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
28
BookAStar/BookAStar/Model/Access/BlackListed.cs
Normal file
28
BookAStar/BookAStar/Model/Access/BlackListed.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using BookAStar.Model.Access;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yavsc.Models;
|
||||
|
||||
namespace BookAStar.Model.Access
|
||||
{
|
||||
public class BlackListed : IBlackListed
|
||||
{
|
||||
public long Id
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string OwnerId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string UserId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +1,11 @@
|
||||
using BookAStar.Helpers;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.Model.Auth.Account
|
||||
{
|
||||
{
|
||||
public class User : INotifyPropertyChanged
|
||||
{
|
||||
private string id;
|
||||
@ -81,6 +76,20 @@ namespace BookAStar.Model.Auth.Account
|
||||
OnPropertyChanged("Avatar");
|
||||
}
|
||||
}
|
||||
private string address;
|
||||
public string Address
|
||||
{
|
||||
get
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
address = value;
|
||||
OnPropertyChanged("Address");
|
||||
}
|
||||
}
|
||||
[JsonIgnore]
|
||||
public ImageSource AvatarSource
|
||||
{
|
||||
|
@ -1,15 +1,16 @@
|
||||
using BookAStar.Interfaces;
|
||||
using BookAStar.Model.Social;
|
||||
|
||||
using System;
|
||||
|
||||
namespace BookAStar.Model
|
||||
namespace BookAStar.Model.Social
|
||||
{
|
||||
public class BookQueryData : IBookQueryData
|
||||
public class BookQuery
|
||||
{
|
||||
public ClientProviderInfo Client { get; set; }
|
||||
public Location Location { get; set; }
|
||||
public long Id { get; set; }
|
||||
public DateTime EventDate { get; set; }
|
||||
public decimal? Previsionnal { get; set; }
|
||||
public string Reason { get; set; }
|
||||
public bool Read { get; set; }
|
||||
}
|
||||
}
|
12
BookAStar/BookAStar/Model/Booking/MusicalPreference.cs
Normal file
12
BookAStar/BookAStar/Model/Booking/MusicalPreference.cs
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
namespace BookAStar.Model.Social
|
||||
{
|
||||
|
||||
public class MusicalPreference : MusicalTendency {
|
||||
|
||||
public long OwnerId { get; set; }
|
||||
public int Rate { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
13
BookAStar/BookAStar/Model/Booking/MusicalTendency.cs
Normal file
13
BookAStar/BookAStar/Model/Booking/MusicalTendency.cs
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
namespace BookAStar.Model.Social
|
||||
{
|
||||
|
||||
public class MusicalTendency {
|
||||
|
||||
public long Id {get; set; }
|
||||
|
||||
public string Name { get ; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -12,22 +12,14 @@ namespace BookAStar.Model
|
||||
public string Avatar { get; set; }
|
||||
|
||||
public string UserId { get; set; }
|
||||
// TODO Get User Professional status existence as a boolean
|
||||
// And hack the avatar with
|
||||
public int Rate { get; set; }
|
||||
|
||||
public string EMail { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public Location BillingAddress { get; set; }
|
||||
// TODO Get User Professional status existence as a boolean
|
||||
// And hack the avatar with
|
||||
[JsonIgnore]
|
||||
public ImageSource AvatarOrNot
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserHelpers.Avatar(Avatar);
|
||||
}
|
||||
}
|
||||
|
||||
public string ChatHubConnectionId { get; set; }
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BookAStar.Data;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BookAStar.Model.Social.Messaging
|
||||
{
|
||||
@ -11,5 +10,6 @@ namespace BookAStar.Model.Social.Messaging
|
||||
public DateTime Date { get; set; }
|
||||
public string SenderId { get; set; }
|
||||
public string Message { get; set; }
|
||||
public bool Read { get; set; }
|
||||
}
|
||||
}
|
27
BookAStar/BookAStar/Model/Social/Chat/Connection.cs
Normal file
27
BookAStar/BookAStar/Model/Social/Chat/Connection.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YavscLib;
|
||||
|
||||
namespace BookAStar.Model.Social.Chat
|
||||
{
|
||||
public class Connection : IConnection
|
||||
{
|
||||
public bool Connected
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string ConnectionId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string UserAgent
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
10
BookAStar/BookAStar/Model/Social/LocationType.cs
Normal file
10
BookAStar/BookAStar/Model/Social/LocationType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
namespace BookAStar.Model.Social
|
||||
{
|
||||
public class LocationType
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ namespace BookAStar.Model.Workflow.Messaging
|
||||
/// <summary>
|
||||
/// Query, for a date, with a given perfomer, at this given place.
|
||||
/// </summary>
|
||||
|
||||
public class BookQuery {
|
||||
/// <summary>
|
||||
/// The command identifier
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
namespace Yavsc.Models
|
||||
namespace Yavsc.Model
|
||||
{
|
||||
public partial class Tag
|
||||
{
|
||||
|
@ -1,6 +1,4 @@
|
||||
using BookAStar.Data;
|
||||
using BookAStar.Helpers;
|
||||
using BookAStar.Model.Interfaces;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -8,6 +6,9 @@ using System.Linq;
|
||||
|
||||
namespace BookAStar.Model.Workflow
|
||||
{
|
||||
using Data;
|
||||
using Interfaces;
|
||||
using Social;
|
||||
public partial class Estimate : IEstimate
|
||||
{
|
||||
public long Id { get; set; }
|
||||
@ -26,6 +27,7 @@ namespace BookAStar.Model.Workflow
|
||||
/// <returns></returns>
|
||||
public List<string> AttachedGraphics { get; set; }
|
||||
[JsonIgnore]
|
||||
// form in db
|
||||
public string AttachedGraphicsString
|
||||
{
|
||||
get { return AttachedGraphics==null?null:string.Join(":", AttachedGraphics); }
|
||||
@ -39,6 +41,7 @@ namespace BookAStar.Model.Workflow
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<string> AttachedFiles { get; set; }
|
||||
// form in db
|
||||
[JsonIgnore]
|
||||
public string AttachedFilesString
|
||||
{
|
||||
@ -47,16 +50,28 @@ namespace BookAStar.Model.Workflow
|
||||
}
|
||||
|
||||
public string OwnerId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public ClientProviderInfo Owner
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(OwnerId))
|
||||
{
|
||||
var dm = DataManager.Instance;
|
||||
return dm.Contacts.LocalGet(OwnerId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public string ClientId { get; set; }
|
||||
[JsonIgnore]
|
||||
public BookQueryData Query
|
||||
public BookQuery Query
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CommandId.HasValue)
|
||||
{
|
||||
var dm = DataManager.Current;
|
||||
var dm = DataManager.Instance;
|
||||
return dm.BookQueries.LocalGet(CommandId.Value);
|
||||
}
|
||||
return null;
|
||||
@ -67,7 +82,7 @@ namespace BookAStar.Model.Workflow
|
||||
{
|
||||
get
|
||||
{
|
||||
return DataManager.Current.Contacts.LocalGet(ClientId);
|
||||
return DataManager.Instance.Contacts.LocalGet(ClientId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,9 +92,14 @@ namespace BookAStar.Model.Workflow
|
||||
return Bill?.Aggregate((decimal)0, (t, l) => t + l.Count * l.UnitaryCost) ?? (decimal)0;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime LatestValidationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This validation comes first from the provider.
|
||||
/// </summary>
|
||||
public DateTime ProviderValidationDate { get; set; }
|
||||
/// <summary>
|
||||
/// Date for the agreement from the client
|
||||
/// </summary>
|
||||
public DateTime ClientApprouvalDate { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="BookAStar.Pages.ChatPage"
|
||||
x:Class="BookAStar.Pages.Chat.ChatPage"
|
||||
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
||||
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
|
||||
xmlns:toolkit="clr-namespace:XLabs.Forms.Mvvm;assembly=XLabs.Forms"
|
||||
xmlns:converters="clr-namespace:BookAStar.Converters;assembly=BookAStar"
|
||||
xmlns:local="clr-namespace:BookAStar;Assembly:BookAStar"
|
||||
xmlns:extensions="clr-namespace:BookAStar.Extensions;assembly=BookAStar"
|
||||
>
|
||||
|
||||
Style="{StaticResource PageStyle}" >
|
||||
<TabbedPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<converters:SignalRConnectionStateToObject x:Key="cxToStyleImage" x:TypeArguments="Style">
|
||||
@ -100,20 +99,15 @@
|
||||
<ContentPage Title="Contacts" Icon="peer_to_peer.png" >
|
||||
<StackLayout Padding="5, 5, 5, 5">
|
||||
<StackLayout Spacing = "12"
|
||||
Orientation = "Horizontal"
|
||||
Padding="5, 0, 5, 0">
|
||||
<Entry x:Name="pvEntry" Placeholder = "enter your private message"
|
||||
VerticalOptions = "Center"
|
||||
HorizontalOptions = "FillAndExpand"></Entry>
|
||||
<!--
|
||||
<controls:ExtendedPicker x:Name="contactPicker" Display="{Binding UserName}"></controls:ExtendedPicker>
|
||||
-->
|
||||
<controls:ExtendedPicker x:Name="contactPicker" ItemsSource="{Binding Contacts}" />
|
||||
<Button x:Name="sendPVButton" Text = "Send" HorizontalOptions = "End"
|
||||
VerticalOptions = "Center"></Button>
|
||||
Orientation = "Horizontal">
|
||||
|
||||
</StackLayout>
|
||||
<ListView x:Name="PVList" HasUnevenRows="true" ItemsSource="{Binding PVs}">
|
||||
<ListView.ItemTemplate HeightRequest="80"
|
||||
|
||||
<views:UserListView x:Name="chatUserList" />
|
||||
|
||||
<StackLayout BindingContext="{x:Reference Name=chatUserList}" IsVisible="{Binding HasASelection}">
|
||||
<ListView x:Name="pvList" HasUnevenRows="true" ItemsSource="{Binding SelectedUser.PrivateMessages}" BindingContext="{x:Reference Name=chatUserList}">
|
||||
<ListView.ItemTemplate HeightRequest="80"
|
||||
VerticalOptions="StartAndExpand">
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
@ -129,7 +123,13 @@
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<!-- <views:UserListView ItemsSource="" /> -->
|
||||
|
||||
<Entry x:Name="pvEntry" Placeholder = "enter your private message"
|
||||
VerticalOptions = "Center" HorizontalOptions = "FillAndExpand"></Entry>
|
||||
|
||||
<Button x:Name="sendPVButton" Text = "Send" HorizontalOptions = "End"
|
||||
VerticalOptions = "Center"></Button>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
|
||||
</ContentPage>
|
@ -3,7 +3,7 @@ using System.Diagnostics;
|
||||
using Microsoft.AspNet.SignalR.Client;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.Pages
|
||||
namespace BookAStar.Pages.Chat
|
||||
{
|
||||
using Data;
|
||||
using System.Linq;
|
||||
@ -12,14 +12,28 @@ namespace BookAStar.Pages
|
||||
public partial class ChatPage : TabbedPage
|
||||
{
|
||||
public string ChatUser { get; set; }
|
||||
public ChatPage(ChatViewModel model)
|
||||
{
|
||||
Init();
|
||||
BindingContext = model;
|
||||
}
|
||||
|
||||
public ChatPage()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Title = "Chat";
|
||||
BindingContext = new ChatViewModel();
|
||||
|
||||
/*
|
||||
ToolbarItems.Add(new ToolbarItem(
|
||||
name: "...",
|
||||
icon: null,
|
||||
activated: () => { })); */
|
||||
App.ChatHubConnection.StateChanged += ChatHubConnection_StateChanged;
|
||||
sendButton.Clicked += async (sender, args) =>
|
||||
{
|
||||
IsBusy = true;
|
||||
@ -38,30 +52,34 @@ namespace BookAStar.Pages
|
||||
|
||||
IsBusy = false;
|
||||
};
|
||||
|
||||
sendPVButton.Clicked += async (sender, args) =>
|
||||
{
|
||||
string userName = contactPicker.SelectedItem as string;
|
||||
if (string.IsNullOrEmpty(userName)) return;
|
||||
var user = DataManager.Current.Contacts.Single(
|
||||
c => c.UserName == userName);
|
||||
if (string.IsNullOrEmpty(user.ChatHubConnectionId)) return;
|
||||
IsBusy = true;
|
||||
try
|
||||
|
||||
{
|
||||
await App.ChatHubProxy.Invoke<string>("SendPV", user.ChatHubConnectionId, pvEntry.Text);
|
||||
pvEntry.Text = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex);
|
||||
}
|
||||
IsBusy = false;
|
||||
};
|
||||
chatUserList.BindingContext = DataManager.Instance.ChatUsers;
|
||||
|
||||
|
||||
sendPVButton.Clicked += (sender, args) =>
|
||||
{
|
||||
var dest = chatUserList.SelectedUser;
|
||||
if (dest!=null)
|
||||
{
|
||||
IsBusy = true;
|
||||
try
|
||||
{
|
||||
foreach (var cx in dest.ObservableConnections)
|
||||
{
|
||||
if (cx.Connected)
|
||||
App.ChatHubProxy.Invoke<string>("SendPV", cx.ConnectionId, pvEntry.Text);
|
||||
}
|
||||
pvEntry.Text = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex);
|
||||
}
|
||||
IsBusy = false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void ChatHubConnection_StateChanged(StateChange obj)
|
||||
{
|
||||
Xamarin.Forms.Device.BeginInvokeOnMainThread(
|
51
BookAStar/BookAStar/Pages/ClientPages/SearchPage.xaml
Normal file
51
BookAStar/BookAStar/Pages/ClientPages/SearchPage.xaml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="BookAStar.Pages.ClientPages.SearchPage"
|
||||
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
||||
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
|
||||
xmlns:toolkit="clr-namespace:XLabs.Forms.Mvvm;assembly=XLabs.Forms"
|
||||
xmlns:converters="clr-namespace:BookAStar.Converters;assembly=BookAStar"
|
||||
xmlns:local="clr-namespace:BookAStar;Assembly:BookAStar"
|
||||
xmlns:extensions="clr-namespace:BookAStar.Extensions;assembly=BookAStar"
|
||||
|
||||
Style="{StaticResource PageStyle}" >
|
||||
|
||||
<TabbedPage.Children>
|
||||
<ContentPage Title="Une star" Icon="">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Editor x:Name="search_phrase" HorizontalOptions="FillAndExpand"/>
|
||||
<Button x:Name="btn_update" HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
<DatePicker x:Name="search_date" />
|
||||
</ContentPage>
|
||||
</TabbedPage.Children>
|
||||
<TabbedPage.Children>
|
||||
<ContentPage Title="Un DJ" Icon="">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Editor x:Name="search_phrase" HorizontalOptions="FillAndExpand"/>
|
||||
<Button x:Name="btn_update" HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
<DatePicker x:Name="search_date" />
|
||||
</ContentPage>
|
||||
</TabbedPage.Children>
|
||||
<TabbedPage.Children>
|
||||
<ContentPage Title="Un chanteur" Icon="">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Editor x:Name="search_phrase" HorizontalOptions="FillAndExpand"/>
|
||||
<Button x:Name="btn_update" HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
<DatePicker x:Name="search_date" />
|
||||
</ContentPage>
|
||||
</TabbedPage.Children>
|
||||
<TabbedPage.Children>
|
||||
<ContentPage Title="Une formation musicale" Icon="">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Editor x:Name="search_phrase" HorizontalOptions="FillAndExpand"/>
|
||||
<Button x:Name="btn_update" HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
<DatePicker x:Name="search_date" />
|
||||
</ContentPage>
|
||||
</TabbedPage.Children>
|
||||
|
||||
</TabbedPage>
|
@ -6,11 +6,11 @@ using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.Pages
|
||||
namespace BookAStar.Pages.ClientPages
|
||||
{
|
||||
public partial class HomePage : ContentPage
|
||||
public partial class SearchPage : TabbedPage
|
||||
{
|
||||
public HomePage()
|
||||
public SearchPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
@ -3,7 +3,8 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:signature="clr-namespace:SignaturePad.Forms;assembly=SignaturePad.Forms"
|
||||
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
|
||||
x:Class="BookAStar.ViewModels.Signing.DocSigning">
|
||||
x:Class="BookAStar.ViewModels.Signing.Signing"
|
||||
Style="{StaticResource PageStyle}">
|
||||
<StackLayout>
|
||||
<views:MarkdownView x:Name="mdView"
|
||||
Editable="False"
|
||||
|
@ -9,9 +9,9 @@ using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.ViewModels.Signing
|
||||
{
|
||||
public partial class DocSigning : ContentPage
|
||||
public partial class Signing : ContentPage
|
||||
{
|
||||
public DocSigning()
|
||||
public Signing()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
@ -30,29 +30,34 @@
|
||||
<ScrollView>
|
||||
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
|
||||
<ListView RefreshCommand="{Binding RefreshQueries}" IsPullToRefreshEnabled="True"
|
||||
ItemsSource="{Binding Queries}" x:Name="list" ItemTapped="OnViewDetail" HasUnevenRows="true" RowHeight="80">
|
||||
<ListView.ItemTemplate HeightRequest="80" VerticalOptions="StartAndExpand">
|
||||
ItemsSource="{Binding Queries}" x:Name="list" ItemTapped="OnViewDetail" HasUnevenRows="true"
|
||||
SeparatorVisibility="Default" SeparatorColor="Black">
|
||||
<ListView.ItemTemplate VerticalOptions="StartAndExpand">
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<ViewCell.View>
|
||||
<StackLayout Orientation="Horizontal" Padding="10,10,10,10" VerticalOptions="StartAndExpand">
|
||||
<StackLayout Orientation="Vertical"
|
||||
HeightRequest="80" VerticalOptions="StartAndExpand">
|
||||
|
||||
<StackLayout Orientation="Vertical" >
|
||||
<Image Source="{Binding Client.Avatar}" />
|
||||
<Label Text="{Binding Client.UserName}"
|
||||
Style="{StaticResource labelStyle}"></Label>
|
||||
</StackLayout>
|
||||
|
||||
<Label LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontSize="12" FontFamily="Italic"/>
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
|
||||
<Label LineBreakMode="WordWrap" Text="{Binding Location.Address}"/>
|
||||
<Label Text="{Binding Previsionnal}" />
|
||||
<Label Text="{Binding Id}" HorizontalTextAlignment="End"/>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Source="{Binding Avatar}" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Grid.RowSpan="2" Text="{Binding Client.UserName}" Style="{StaticResource labelStyle}"></Label>
|
||||
<Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Grid.RowSpan="2" Text="{Binding Data.Reason}"></Label>
|
||||
<Label Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontFamily="Italic"/>
|
||||
<Label Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" LineBreakMode="WordWrap" Text="{Binding Location.Address}"/>
|
||||
<Label Grid.Row="4" Grid.Column="1" Text="{Binding Previsionnal}" />
|
||||
<Label Grid.Row="4" Grid.Column="2" Text="{Binding Id}" />
|
||||
</Grid>
|
||||
|
||||
</ViewCell.View>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
|
@ -14,20 +14,34 @@ namespace BookAStar.Pages
|
||||
public BookQueriesPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
var model = new BookQueriesViewModel();
|
||||
model.RefreshQueries =
|
||||
new Command( () => {
|
||||
DataManager.Current.BookQueries.Execute(null);
|
||||
this.list.EndRefresh();
|
||||
});
|
||||
|
||||
BindingContext = new BookQueriesViewModel();
|
||||
}
|
||||
|
||||
public BookQueriesPage(BookQueriesViewModel model)
|
||||
{
|
||||
InitializeComponent();
|
||||
BindingContext = model;
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
BookQueriesViewModel model = (BookQueriesViewModel) BindingContext;
|
||||
if (model!=null)
|
||||
{
|
||||
model.RefreshQueries =
|
||||
new Command(() =>
|
||||
{
|
||||
DataManager.Instance.BookQueries.Execute(null);
|
||||
this.list.EndRefresh();
|
||||
});
|
||||
}
|
||||
base.OnBindingContextChanged();
|
||||
}
|
||||
|
||||
private void OnViewDetail(object sender, ItemTappedEventArgs e)
|
||||
{
|
||||
BookQueryData data = e.Item as BookQueryData;
|
||||
App.NavigationService.NavigateTo<BookQueryPage>(true,data);
|
||||
var item = e.Item as BookQueryViewModel;
|
||||
App.NavigationService.NavigateTo<BookQueryPage>(true,item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,20 +19,24 @@
|
||||
|
||||
<StackLayout x:Name="bookQueryLayout">
|
||||
<StackLayout Orientation="Vertical">
|
||||
<Image Source="{Binding Client.AvatarOrNot}" Aspect="AspectFit" VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}"/>
|
||||
<Image Source="{Binding Avatar}" Aspect="AspectFit" VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}"/>
|
||||
<Label Text="{Binding Client.UserName}" />
|
||||
<Label Text="{Binding EventDate, StringFormat='le {0:dddd d MMMM yyyy à hh:mm}'}" />
|
||||
<Label Text="{Binding Data.Reason}" />
|
||||
<Label Text="{Binding Location.Address}" />
|
||||
<Label Text="{Binding Previsional}" />
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
|
||||
<maps:Map x:Name="map" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></maps:Map>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Button Text="{x:Static local:Strings.ViewEstimate}"
|
||||
BorderRadius="50" BorderWidth="2" BorderColor="Aqua" x:Name ="btn"
|
||||
IsEnabled="{Binding EstimationDone}"
|
||||
Clicked="OnViewEstimate" Image="exclam.png" />
|
||||
|
||||
<Button Text="{Binding EditEstimateButtonText}" Clicked="OnEditEstimate" />
|
||||
<Button Text="{x:Static local:Strings.DeclineQuery}" Clicked="OnDropQuery" />
|
||||
<Button Text="{x:Static local:Strings.BlockThisUser}" Clicked="OnBlockThisUser" />
|
||||
<Button Text="{x:Static local:Strings.ViewEstimate}"
|
||||
BorderRadius="50" BorderWidth="2" BorderColor="Aqua" x:Name ="btn"
|
||||
VisualElement.IsVisible="{Binding EstimationDone}"
|
||||
Clicked="OnViewEstimate" Image="exclam.png" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
|
@ -7,14 +7,14 @@ namespace BookAStar.Pages
|
||||
{
|
||||
using Data;
|
||||
using EstimatePages;
|
||||
using Model;
|
||||
using Model.Social;
|
||||
using Model.Workflow;
|
||||
using ViewModels.EstimateAndBilling;
|
||||
|
||||
public partial class BookQueryPage : ContentPage
|
||||
{
|
||||
|
||||
public BookQueryData BookQuery
|
||||
public BookQuery BookQuery
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -32,14 +32,14 @@ namespace BookAStar.Pages
|
||||
var pin = new Pin
|
||||
{
|
||||
Type = PinType.SavedPin,
|
||||
Position = new Position(
|
||||
lat, lon),
|
||||
Position = new Xamarin.Forms.Maps.Position
|
||||
(lat, lon),
|
||||
Label = BookQuery.Client.UserName,
|
||||
Address = BookQuery.Location.Address
|
||||
};
|
||||
map.Pins.Add(pin);
|
||||
map.MoveToRegion(MapSpan.FromCenterAndRadius(
|
||||
new Position(lat, lon), Distance.FromMeters(100)));
|
||||
new Xamarin.Forms.Maps.Position(lat, lon), Distance.FromMeters(100)));
|
||||
}
|
||||
|
||||
}
|
||||
@ -47,14 +47,14 @@ namespace BookAStar.Pages
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
public BookQueryPage(BookQueryData bookQuery=null)
|
||||
public BookQueryPage(BookQueryViewModel bookQuery =null)
|
||||
{
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
// when TODO update?
|
||||
// Task.Run( async () => { bookQuery = await App.CurrentApp.DataManager.BookQueries.Get(bookQueryId); });
|
||||
|
||||
BindingContext = new BookQueryViewModel(bookQuery);
|
||||
BindingContext = bookQuery;
|
||||
}
|
||||
|
||||
private void OnEditEstimate(object sender, EventArgs ev)
|
||||
@ -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.Instance.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
|
||||
DataManager.Instance.Contacts.Merge(BookQuery.Client);
|
||||
DataManager.Instance.Contacts.SaveEntity();
|
||||
editEstimateViewModel = new EditEstimateViewModel( new Estimate
|
||||
{
|
||||
ClientId = BookQuery.Client.UserId,
|
||||
CommandId = BookQuery.Id,
|
||||
OwnerId = MainSettings.CurrentUser.Id,
|
||||
Id = 0
|
||||
};
|
||||
editEstimateViewModel = new EditEstimateViewModel(estimateToEdit);
|
||||
});
|
||||
DataManager.Instance.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)
|
||||
@ -118,5 +112,13 @@ namespace BookAStar.Pages
|
||||
}
|
||||
base.OnSizeAllocated(width, height);
|
||||
}
|
||||
private void OnBlockThisUser(object sender, EventArgs ev)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
private void OnDropQuery(object sender, EventArgs ev)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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="descriptionValidator" MaxLength="512" />
|
||||
<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">
|
||||
@ -95,7 +102,7 @@
|
||||
<behaviors:DecimalValidatorBehavior x:Name="unitCostValidator" />
|
||||
</Entry.Behaviors>
|
||||
</Entry>
|
||||
<Label Text="€" Style="{StaticResource BigLabel}" />
|
||||
<Label Text="€" Style="{StaticResource BigLabelStyle}" />
|
||||
<Image x:Name="unitaryCostSuccessErrorImage"
|
||||
Style="{Binding Source={x:Reference unitCostValidator},
|
||||
Path=IsValid,
|
||||
@ -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,8 +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>
|
||||
@ -13,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="*" />
|
||||
@ -34,18 +55,20 @@
|
||||
<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" />
|
||||
|
||||
</views:MarkdownView.Behaviors>
|
||||
</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>
|
||||
@ -54,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>
|
||||
@ -64,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>
|
||||
@ -73,10 +100,9 @@
|
||||
<StackLayout Orientation="Vertical">
|
||||
<Button Text="Ajouter une ligne de facture" Clicked="OnNewCommanLine"></Button>
|
||||
<Label FormattedText="{Binding FormattedTotal}"/>
|
||||
<Button Text="Valider ce devis" Clicked="OnEstimateValidated" ></Button>
|
||||
<Button x:Name="btnValidate" Text="Valider ce devis" Clicked="OnEstimateValidated" IsEnabled="{Binding ViewModelState.IsValid}" ></Button>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
@ -4,16 +4,36 @@ using Xamarin.Forms;
|
||||
namespace BookAStar.Pages
|
||||
{
|
||||
using Data;
|
||||
using EstimatePages;
|
||||
using Model.Workflow;
|
||||
using ViewModels.EstimateAndBilling;
|
||||
using ViewModels.Signing;
|
||||
|
||||
public partial class EditEstimatePage : ContentPage
|
||||
{
|
||||
|
||||
public EditEstimateViewModel Model
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EditEstimateViewModel)BindingContext;
|
||||
}
|
||||
}
|
||||
public EditEstimatePage(EditEstimateViewModel model)
|
||||
{
|
||||
InitializeComponent();
|
||||
BindingContext = model;
|
||||
Model.CheckCommand = new Action<Estimate, ViewModels.Validation.ModelState>(
|
||||
(e, m) =>
|
||||
{
|
||||
foreach (var line in model.Bill)
|
||||
{
|
||||
line.Check();
|
||||
if (!line.ViewModelState.IsValid)
|
||||
model.ViewModelState.AddError("Bill", "invalid line");
|
||||
}
|
||||
});
|
||||
|
||||
InitializeComponent();
|
||||
Model.Check();
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
@ -24,7 +44,7 @@ namespace BookAStar.Pages
|
||||
|
||||
private void EditEstimatePage_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
DataManager.Current.EstimationCache.SaveEntity();
|
||||
DataManager.Instance.EstimationCache.SaveEntity();
|
||||
}
|
||||
|
||||
protected override void OnSizeAllocated(double width, double height)
|
||||
@ -46,54 +66,62 @@ namespace BookAStar.Pages
|
||||
var bill = ((EditEstimateViewModel)BindingContext).Bill;
|
||||
var lineView = new BillingLineViewModel(com)
|
||||
{ ValidateCommand = new Command(() => {
|
||||
bill.Add(com);
|
||||
DataManager.Current.EstimationCache.SaveEntity();
|
||||
bill.Add(new BillingLineViewModel(com));
|
||||
DataManager.Instance.EstimationCache.SaveEntity();
|
||||
})};
|
||||
lineView.PropertyChanged += LineView_PropertyChanged;
|
||||
App.NavigationService.NavigateTo<EditBillingLinePage>(
|
||||
true, lineView );
|
||||
}
|
||||
protected void OnEditLine(object sender, ItemTappedEventArgs e)
|
||||
{
|
||||
var line = (BillingLine)e.Item;
|
||||
var bill = ((EditEstimateViewModel)BindingContext).Bill;
|
||||
var lineView = new BillingLineViewModel(line)
|
||||
{
|
||||
ValidateCommand = new Command(() => {
|
||||
DataManager.Current.EstimationCache.SaveEntity();
|
||||
})
|
||||
};
|
||||
lineView.PropertyChanged += LineView_PropertyChanged;
|
||||
|
||||
lineView.PropertyChanged += LineView_PropertyChanged;
|
||||
var line = (BillingLineViewModel)e.Item;
|
||||
var evm = ((EditEstimateViewModel)BindingContext);
|
||||
// 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(() =>
|
||||
{
|
||||
evm.Check();
|
||||
DataManager.Instance.EstimationCache.SaveEntity();
|
||||
});
|
||||
// and setup a removal command, that was not expected at creation time
|
||||
line.RemoveCommand = new Command(() =>
|
||||
{
|
||||
evm.Bill.Remove(line);
|
||||
evm.Check();
|
||||
DataManager.Instance.EstimationCache.SaveEntity();
|
||||
});
|
||||
App.NavigationService.NavigateTo<EditBillingLinePage>(
|
||||
true, lineView );
|
||||
true, line );
|
||||
BillListView.SelectedItem = null;
|
||||
}
|
||||
|
||||
|
||||
private void LineView_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
protected async void OnEstimateValidated(object sender, EventArgs e)
|
||||
{
|
||||
DataManager.Current.EstimationCache.SaveEntity();
|
||||
}
|
||||
|
||||
protected void OnEstimateValidated(object sender, EventArgs e)
|
||||
{
|
||||
var evm = (EditEstimateViewModel)BindingContext;
|
||||
if (evm.Data.Id == 0)
|
||||
|
||||
var thisPage = this;
|
||||
var evm = (EditEstimateViewModel) BindingContext;
|
||||
var cmd = new Command<bool>( async (validated) =>
|
||||
{
|
||||
DataManager.Current.Estimates.Create(evm.Data);
|
||||
// we have to manually add this item in our local collection,
|
||||
// since we could prefer to update the whole collection
|
||||
// from server, or whatever other scenario
|
||||
DataManager.Current.Estimates.Add(evm.Data);
|
||||
} else
|
||||
if (validated) {
|
||||
DataManager.Instance.EstimationCache.Remove(evm);
|
||||
DataManager.Instance.EstimationCache.SaveEntity();
|
||||
}
|
||||
await thisPage.Navigation.PopAsync();
|
||||
});
|
||||
var response = await App.DisplayActionSheet(
|
||||
Strings.SignOrNot, Strings.DonotsignEstimate,
|
||||
Strings.CancelValidation, new string[] { Strings.Sign });
|
||||
if (response == Strings.Sign)
|
||||
{
|
||||
DataManager.Current.Estimates.Update(evm.Data);
|
||||
App.NavigationService.NavigateTo<EstimateSigningPage>(true,
|
||||
new EstimateSigningViewModel(evm.Data) { ValidationCommand = cmd });
|
||||
}
|
||||
DataManager.Current.Estimates.SaveEntity();
|
||||
DataManager.Current.EstimationCache.Remove(evm);
|
||||
DataManager.Current.EstimationCache.SaveEntity();
|
||||
Navigation.PopAsync();
|
||||
else if (response == Strings.CancelValidation)
|
||||
return;
|
||||
else cmd.Execute(true);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
<?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.Resources>
|
||||
<ResourceDictionary>
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="Style" Value="{StaticResource ContentLabelStyle}" />
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Style" Value="{StaticResource ButtonStyle}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<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}" Style="{StaticResource BigLabelStyle}" />
|
||||
|
||||
<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 Orientation="Horizontal">
|
||||
<Image Source="{Binding ProSignImage}" HorizontalOptions="Start"></Image>
|
||||
<Image Source="{Binding CliSignImage}" HorizontalOptions="End"></Image>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
<signature:SignaturePadView x:Name="padView"
|
||||
VerticalOptions="FillAndExpand"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
BackgroundColor="White"
|
||||
CaptionText="{Binding Data.Owner.UserName}" CaptionTextColor="Black"
|
||||
ClearText="Effacer!" 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,74 @@
|
||||
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.Instance.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.Instance.Estimates.SignAsProvider(estimate, pngStream);
|
||||
DataManager.Instance.Estimates.SaveEntity();
|
||||
await Navigation.PopAsync();
|
||||
|
||||
var ParentValidationCommand = ((EstimateSigningViewModel)BindingContext).ValidationCommand;
|
||||
if (ParentValidationCommand != null)
|
||||
ParentValidationCommand.Execute(true);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="BookAStar.Pages.EstimatesClientPage">
|
||||
|
||||
<Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
|
||||
x:Class="BookAStar.Pages.EstimatesClientPage"
|
||||
Style="{StaticResource PageStyle}">
|
||||
|
||||
<ScrollView>
|
||||
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
|
||||
<ListView RefreshCommand="{Binding RefreshCommand}" IsPullToRefreshEnabled="True"
|
||||
ItemsSource="{Binding Estimates}" x:Name="estimates" ItemTapped="OnViewDetail" HasUnevenRows="true" RowHeight="80">
|
||||
<ListView.ItemTemplate HeightRequest="80" VerticalOptions="StartAndExpand">
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<ViewCell.View>
|
||||
<StackLayout Orientation="Horizontal" Padding="10,10,10,10" VerticalOptions="StartAndExpand">
|
||||
<StackLayout Orientation="Vertical"
|
||||
HeightRequest="80" VerticalOptions="StartAndExpand">
|
||||
|
||||
<StackLayout Orientation="Vertical" >
|
||||
<Image Source="{Binding Owner.Avatar}" />
|
||||
<Label Text="{Binding Client.UserName}"
|
||||
Style="{StaticResource labelStyle}"></Label>
|
||||
</StackLayout>
|
||||
|
||||
<Label LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontSize="12" FontFamily="Italic"/>
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
|
||||
<Label LineBreakMode="WordWrap" Text="{Binding Location.Address}"/>
|
||||
<Label Text="{Binding Previsionnal}"/>
|
||||
<Label Text="{Binding Id}" HorizontalTextAlignment="End"/>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ViewCell.View>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="BookAStar.Pages.EstimatesProviderPage">
|
||||
x:Class="BookAStar.Pages.EstimatesProviderPage"
|
||||
Style="{StaticResource PageStyle}">
|
||||
|
||||
<ScrollView>
|
||||
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
|
||||
|
@ -33,9 +33,6 @@
|
||||
</Grid>
|
||||
|
||||
<Label Text="{Binding Title}" />
|
||||
|
||||
<Label Text="{Binding Description}" />
|
||||
|
||||
<views:MarkdownView x:Name="mdview"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
Markdown="{Binding Description}"
|
||||
|
103
BookAStar/BookAStar/Pages/HomePage.xaml
Normal file
103
BookAStar/BookAStar/Pages/HomePage.xaml
Normal file
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:BookAStar;assembly=BookAStar"
|
||||
x:Class="BookAStar.Pages.HomePage"
|
||||
Style="{StaticResource PageStyle}"
|
||||
Title="Accueil">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="Style" Value="{StaticResource ContentLabelStyle}" />
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Style" Value="{StaticResource ButtonStyle}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<TabbedPage.Children>
|
||||
<!-- La recherche d'un pro -->
|
||||
<TabbedPage Title="{x:Static local:Strings.SearchForAPro}" >
|
||||
</TabbedPage>
|
||||
|
||||
<!--
|
||||
les derniers sons/videos/articles postés
|
||||
-->
|
||||
<ContentPage Title="Blogspot">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Editor x:Name="search_blog_phrase" HorizontalOptions="FillAndExpand"/>
|
||||
<Button x:Name="btn_blog_update" HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
</ContentPage>
|
||||
|
||||
<!--
|
||||
Les demandes devis en attente de réponse (pro)
|
||||
-->
|
||||
<ContentPage Title="Demandes de devis"
|
||||
IsVisible="{Binding UserProfile.IsAPerformer}">
|
||||
<StackLayout BindingContext="{Binding BookQueries}">
|
||||
|
||||
<ListView x:Name="querylist"
|
||||
RefreshCommand="{Binding RefreshQueries}"
|
||||
IsPullToRefreshEnabled="True"
|
||||
ItemsSource="{Binding Queries}"
|
||||
ItemTapped="OnViewBookQueryDetail"
|
||||
HasUnevenRows="true"
|
||||
SeparatorVisibility="Default"
|
||||
SeparatorColor="Black">
|
||||
<ListView.ItemTemplate VerticalOptions="StartAndExpand" >
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<ViewCell.View>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Source="{Binding Avatar}" />
|
||||
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Client.UserName}" Style="{StaticResource LabelStyle}"></Label>
|
||||
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Data.Reason}"></Label>
|
||||
<Label Grid.Row="2" Grid.Column="1" LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontFamily="Italic"/>
|
||||
<Label Grid.Row="3" Grid.Column="1" LineBreakMode="WordWrap" Text="{Binding Location.Address}" />
|
||||
</Grid>
|
||||
</ViewCell.View>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
||||
|
||||
|
||||
<!-- Les signatures de contrat en souffreances (pro) -->
|
||||
<ContentPage Title="Contrats fournisseur" IsVisible="{Binding UserProfile.IsAPerformer}">
|
||||
</ContentPage>
|
||||
|
||||
<!-- Les signatures de contrat en souffreances (client) -->
|
||||
<ContentPage Title="Contrats client" IsVisible="{Binding UserProfile.IsAPerformer}">
|
||||
</ContentPage>
|
||||
|
||||
<!-- Les annonces pro (pro) -->
|
||||
<ContentPage Title="Annonces pro" IsVisible="{Binding UserProfile.IsAPerformer}">
|
||||
<StackLayout Orientation="Horizontal" >
|
||||
<Editor x:Name="search_pub_pro_phrase" HorizontalOptions="FillAndExpand" VerticalOptions="Start"/>
|
||||
<Button x:Name="btn_pro_pub" HorizontalOptions="End" VerticalOptions="Start" Text="Chercher"/>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
||||
|
||||
<!-- les petites annonces des clients (pro) -->
|
||||
<ContentPage Title="Annonces client" Icon="" IsVisible="{Binding UserProfile.IsAPerformer}">
|
||||
<StackLayout Orientation="Horizontal" >
|
||||
<Editor x:Name="search_pub_cli_phrase" HorizontalOptions="FillAndExpand" VerticalOptions="Start"/>
|
||||
<Button x:Name="btn_cli_pub" HorizontalOptions="End" VerticalOptions="Start" Text="Chercher"/>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
||||
</TabbedPage.Children>
|
||||
|
||||
</TabbedPage>
|
55
BookAStar/BookAStar/Pages/HomePage.xaml.cs
Normal file
55
BookAStar/BookAStar/Pages/HomePage.xaml.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar.Pages
|
||||
{
|
||||
using Data;
|
||||
using ViewModels;
|
||||
using ViewModels.EstimateAndBilling;
|
||||
public partial class HomePage
|
||||
{
|
||||
public HomePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public HomePage(HomeViewModel model)
|
||||
{
|
||||
BindingContext = model;
|
||||
}
|
||||
|
||||
public HomeViewModel Model {
|
||||
get {
|
||||
return (HomeViewModel) BindingContext;
|
||||
}
|
||||
set
|
||||
{
|
||||
BindingContext = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
// this technique make this view model
|
||||
// non-sharable between view or pages
|
||||
if (Model != null)
|
||||
{
|
||||
// set the refresh command before using it
|
||||
Model.BookQueries.RefreshQueries =
|
||||
new Command(() =>
|
||||
{
|
||||
DataManager.Instance.BookQueries.Execute(null);
|
||||
this.querylist.EndRefresh();
|
||||
});
|
||||
}
|
||||
// Use the new refresh command
|
||||
base.OnBindingContextChanged();
|
||||
|
||||
}
|
||||
|
||||
private void OnViewBookQueryDetail(object sender, ItemTappedEventArgs e)
|
||||
{
|
||||
var item = e.Item as BookQueryViewModel;
|
||||
App.NavigationService.NavigateTo<BookQueryPage>(true, item);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="BookAStar.Pages.HomePage"
|
||||
Style="{StaticResource PageStyle}">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="Style" Value="{StaticResource ContentLabelStyle}" />
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Style" Value="{StaticResource ButtonStyle}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<Label Text="Blah" VerticalOptions="Center" HorizontalOptions="Center" />
|
||||
</ContentPage>
|
@ -1,55 +0,0 @@
|
||||
<?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:local="clr-namespace:BookAStar;Assembly:BookAStar"
|
||||
x:Class="BookAStar.SearchPage" Title="Page de recherche"
|
||||
Style="{StaticResource PageStyle}">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="Style" Value="{StaticResource ContentLabelStyle}" />
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Style" Value="{StaticResource ButtonStyle}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
|
||||
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Editor x:Name="search_phrase" HorizontalOptions="FillAndExpand"/>
|
||||
<Button x:Name="btn_update" HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
<DatePicker x:Name="search_date" />
|
||||
|
||||
<ListView x:Name="list" ItemsSource="{x:Static local:Manager.Events}"
|
||||
HasUnevenRows="true">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<ViewCell.View>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Image Source="{Binding ImgLocator}" HeightRequest="80" />
|
||||
<StackLayout Orientation="Vertical">
|
||||
<Label Text="{Binding Title}"/>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<StackLayout><Label Text="Heure:" FontAttributes="Italic" FontSize="9" />
|
||||
<Label Text="{Binding StartDate, StringFormat='{0:H:mm}'}" VerticalOptions="End"/>
|
||||
</StackLayout>
|
||||
<StackLayout><Label Text="Lieu:" FontAttributes="Italic" FontSize="9" VerticalOptions="End"/>
|
||||
<Label Text="{Binding Location.Name}"/></StackLayout>
|
||||
|
||||
<Label Text="{Binding Promotion}" FontSize="20" TextColor="Yellow" BackgroundColor="#102030"/>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ViewCell.View>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
using System.Collections.ObjectModel;
|
||||
using BookAStar.Model.Social;
|
||||
using BookAStar.Model.Workflow.Messaging;
|
||||
using BookAStar.Pages;
|
||||
|
||||
namespace BookAStar
|
||||
{
|
||||
public partial class SearchPage : ContentPage
|
||||
{
|
||||
public ObservableCollection<LocalizedEvent> Events { get; private set; }
|
||||
public SearchPage ()
|
||||
{
|
||||
|
||||
InitializeComponent ();
|
||||
|
||||
BindingContext = this;
|
||||
Events = Manager.Events;
|
||||
list.ItemTapped += async (object sender, ItemTappedEventArgs e) => {
|
||||
await Navigation.PushAsync(new EventDetail( (YaEvent) e.Item) { Title = "Détail de la soirée" } );
|
||||
};
|
||||
search_date.Date = DateTime.Now;
|
||||
search_date.MinimumDate = DateTime.Now;
|
||||
search_phrase.Text = "Suresnes";
|
||||
btn_update.Clicked += (object sender, EventArgs e) => {
|
||||
//
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,8 @@
|
||||
xmlns:local="clr-namespace:BookAStar;assembly=BookAStar"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="BookAStar.Pages.UserProfile.AccountChooserPage"
|
||||
Title="Paramètres Booking star" Style="{StaticResource PageStyle}"
|
||||
Title="{x:Static local:Strings.UserAccounts}"
|
||||
Style="{StaticResource PageStyle}"
|
||||
xmlns:lc="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
|
||||
xmlns:lb="clr-namespace:XLabs.Forms.Behaviors;assembly=XLabs.Forms">
|
||||
|
||||
@ -13,6 +14,7 @@
|
||||
<ListView x:Name="AccountListView"
|
||||
SeparatorVisibility="Default"
|
||||
VerticalOptions="FillAndExpand"
|
||||
ItemsSource="{x:Static local:MainSettings.AccountList}"
|
||||
>
|
||||
<ListView.Header>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
@ -20,17 +22,18 @@
|
||||
</StackLayout>
|
||||
</ListView.Header>
|
||||
|
||||
<ListView.ItemTemplate HeightRequest="60" VerticalOptions="StartAndExpand">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<Grid Padding="5"
|
||||
ColumnSpacing="10"
|
||||
RowSpacing="2" >
|
||||
<Image Source="{Binding AvatarSource}" HeightRequest="80"
|
||||
x:Name="avatarImage"/>
|
||||
<Label Grid.Column="0" Text="{Binding UserName}" >
|
||||
|
||||
<Image Grid.Column="0" Source="{Binding AvatarSource}" HeightRequest="80" />
|
||||
<Label Grid.Column="1" Text="{Binding UserName}" >
|
||||
</Label>
|
||||
<Label Grid.Column="2" Text="{Binding EMails.ToString()}" />
|
||||
<Label Grid.Column="3" Text="{Binding Roles.ToString()}" />
|
||||
<Label Grid.Column="4" Text="{Binding Address}" />
|
||||
</Grid>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
|
@ -14,37 +14,24 @@ namespace BookAStar.Pages.UserProfile
|
||||
|
||||
public partial class AccountChooserPage : ContentPage
|
||||
{
|
||||
public ICommand RemoteSettingsRefreshCommand { get; private set; }
|
||||
|
||||
|
||||
public AccountChooserPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
AccountListView.ItemsSource = MainSettings.AccountList;
|
||||
|
||||
this.Musical = MainSettings.Musical;
|
||||
this.Environ = MainSettings.Environ;
|
||||
this.BindingContext = this;
|
||||
|
||||
AddAccountBtn.Clicked += AddAccountBtn_Clicked;
|
||||
|
||||
// avatarImage.
|
||||
//RemoveAccountBouton.Clicked += RemoveAccountBouton_Clicked;
|
||||
|
||||
AccountListView.ItemSelected += Accounts_ItemSelected;
|
||||
DumpParam = new RelayGesture((g, x) =>
|
||||
{
|
||||
if (g.GestureType == GestureType.Swipe && g.Direction == Directionality.Left)
|
||||
{
|
||||
RemoveAccount();
|
||||
}
|
||||
});
|
||||
// MainSettings.UserChanged += MainSettings_UserChanged;
|
||||
}
|
||||
// Should be useless
|
||||
private void MainSettings_UserChanged(object sender, EventArgs e)
|
||||
{
|
||||
AccountListView.SelectedItem = MainSettings.CurrentUser;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public RelayGesture DumpParam { get; set; }
|
||||
public ObservableCollection<User> Accounts { get; private set; }
|
||||
public Dictionary<string, double> Musical { get; private set; }
|
||||
public Dictionary<string, double> Environ { get; private set; }
|
||||
|
||||
private void Accounts_ItemSelected(object sender, SelectedItemChangedEventArgs e)
|
||||
{
|
||||
@ -68,7 +55,6 @@ namespace BookAStar.Pages.UserProfile
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
AccountListView.SelectedItem = MainSettings.CurrentUser;
|
||||
}
|
||||
|
||||
private void AddAccountBtn_Clicked(object sender, EventArgs e)
|
||||
|
@ -7,7 +7,7 @@
|
||||
x:Class="BookAStar.Pages.UserProfile.DashboardPage"
|
||||
xmlns:lc="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
|
||||
xmlns:lb="clr-namespace:XLabs.Forms.Behaviors;assembly=XLabs.Forms"
|
||||
Style="{StaticResource PageStyle}">
|
||||
Style="{StaticResource DashboardPageStyle}">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<Style TargetType="Label">
|
||||
@ -21,34 +21,43 @@
|
||||
<ContentPage.Content>
|
||||
<ScrollView>
|
||||
<StackLayout BoxView.Color="{StaticResource ContentBackgroundColor}">
|
||||
<Label Text="{Binding UserName}" Style="{StaticResource LabelPageHeadingStyle}"
|
||||
HorizontalTextAlignment="Center"
|
||||
LineBreakMode="WordWrap" XAlign="Center"
|
||||
></Label>
|
||||
|
||||
|
||||
<Image Source="{Binding Avatar}"
|
||||
VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}" />
|
||||
<views:RatingView Rating="{Binding Rating, Mode=TwoWay}" x:Name="ratingView" />
|
||||
|
||||
<Button Text="{Binding PerformerStatus}" Clicked="OnViewPerformerStatus" />
|
||||
<Button Text="{Binding UserQueries}" Clicked="OnViewUserQueries"
|
||||
VisualElement.IsVisible="{Binding UserIsPro}"/>
|
||||
<lc:GesturesContentView>
|
||||
<Image Source="{Binding Avatar}" HeightRequest="{StaticResource BigUserAvatarSize}" >
|
||||
<lb:Gestures.Interests>
|
||||
<lb:GestureCollection>
|
||||
<lb:GestureInterest GestureType="SingleTap" GestureCommand="{Binding AvatarCommand}" GestureParameter="{Binding Ready}"/>
|
||||
<lb:GestureInterest GestureType="LongPress" GestureCommand="{Binding AvatarCommand}" GestureParameter="{Binding Ready}"/>
|
||||
<lb:GestureInterest GestureType="Swipe" Direction="Left" GestureCommand="{Binding AvatarCommand}" GestureParameter="{Binding Ready}"/>
|
||||
<lb:GestureInterest GestureType="Swipe" Direction="Right" GestureCommand="{Binding AvatarCommand}" GestureParameter="{Binding Ready}"/>
|
||||
</lb:GestureCollection>
|
||||
</lb:Gestures.Interests>
|
||||
</Image>
|
||||
</lc:GesturesContentView>
|
||||
<Button Text="{Binding UserName}" Clicked="OnRefreshQuery" />
|
||||
|
||||
<Button Text="{Binding UserFilesLabel}" Clicked="OnManageFiles" />
|
||||
<StackLayout Orientation="Horizontal" VisualElement.IsVisible="{Binding HaveAnUser}">
|
||||
<Button Text="{Binding UserFilesText}" Clicked="OnManageFiles" />
|
||||
<StackLayout VisualElement.IsVisible="{Binding HaveAnUser}">
|
||||
<Button Text="{Binding PerformerStatus}" Clicked="OnViewPerformerStatus" />
|
||||
<Button Text="{Binding UserQueries}" Clicked="OnViewUserQueries"
|
||||
VisualElement.IsVisible="{Binding IsAPerformer}"/>
|
||||
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Label Text="Recevoir les notifications push" StyleClass="Header" />
|
||||
<Switch IsToggled="{Binding ReceivePushNotifications, Mode=TwoWay}"
|
||||
HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Label Text="Utiliser ma position" StyleClass="Header" />
|
||||
<Switch HorizontalOptions="End" IsToggled="{Binding AllowUseMyPosition, Mode=TwoWay}"/>
|
||||
</StackLayout>
|
||||
<StackLayout Orientation="Horizontal" VerticalOptions="Start"
|
||||
VisualElement.IsVisible="{Binding UserIsPro}" >
|
||||
<Label Text="Ne recevoir de demande de devis que de la part de professionnels uniquement" />
|
||||
<Switch HorizontalOptions="End" IsToggled="{Binding AllowProBookingOnly, Mode=TwoWay}"/>
|
||||
<StackLayout VisualElement.IsVisible="{Binding IsAPerformer}" >
|
||||
<Label Text="{x:Static local:Strings.Profprof}" Style="{StaticResource LabelStyle}"/>
|
||||
<views:RatingView Rating="{Binding Rating, Mode=TwoWay}" x:Name="ratingView" />
|
||||
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
|
||||
<Label Text="{x:Static local:Strings.ClientProRequest}" />
|
||||
<Switch HorizontalOptions="End" IsToggled="{Binding AllowProBookingOnly, Mode=TwoWay}" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
@ -5,7 +5,12 @@ using XLabs.Forms.Behaviors;
|
||||
namespace BookAStar.Pages.UserProfile
|
||||
{
|
||||
using Data;
|
||||
using Helpers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using ViewModels.UserProfile;
|
||||
using XLabs.Forms.Controls;
|
||||
|
||||
public partial class DashboardPage : ContentPage
|
||||
{
|
||||
@ -18,11 +23,43 @@ namespace BookAStar.Pages.UserProfile
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
base.OnBindingContextChanged();
|
||||
// Assert ((DashboardViewModel)BindingContext!=null)
|
||||
((DashboardViewModel)BindingContext).UserNameGesture
|
||||
= new RelayGesture( (gesture,arg) => {
|
||||
ShowPage<AccountChooserPage>(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
public async void OnRefreshQuery(object sender, EventArgs e)
|
||||
{
|
||||
// TODO disable the button when current user is not registered
|
||||
if (MainSettings.CurrentUser==null)
|
||||
ShowPage<AccountChooserPage>(null, true);
|
||||
else
|
||||
{
|
||||
IsBusy = true;
|
||||
using (var client = UserHelpers.CreateJsonClient())
|
||||
{
|
||||
using (var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl))
|
||||
{
|
||||
using (var response = await client.SendAsync(request))
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
string userJson = await response.Content.ReadAsStringAsync();
|
||||
JObject jactiveUser = JObject.Parse(userJson);
|
||||
var username = jactiveUser["UserName"].Value<string>();
|
||||
var roles = jactiveUser["Roles"].Values<string>().ToList();
|
||||
var emails = jactiveUser["EMails"].Values<string>().ToList();
|
||||
var avatar = jactiveUser["Avatar"].Value<string>();
|
||||
var address = jactiveUser["Avatar"].Value<string>();
|
||||
var me = MainSettings.CurrentUser;
|
||||
me.Address = address;
|
||||
me.Avatar = avatar;
|
||||
me.EMails = emails;
|
||||
me.UserName = username;
|
||||
me.Roles = roles;
|
||||
MainSettings.SaveUser(me);
|
||||
}
|
||||
}
|
||||
}
|
||||
IsBusy = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void OnManageFiles(object sender, EventArgs e)
|
||||
|
@ -12,7 +12,7 @@ namespace BookAStar.Pages.UserProfile
|
||||
public UserFiles()
|
||||
{
|
||||
InitializeComponent();
|
||||
var current = DataManager.Current.RemoteFiles.CurrentItem;
|
||||
var current = DataManager.Instance.RemoteFiles.CurrentItem;
|
||||
if (current != null)
|
||||
BindingContext = new DirectoryInfoViewModel(current);
|
||||
else BindingContext = new DirectoryInfoViewModel
|
||||
@ -33,8 +33,8 @@ namespace BookAStar.Pages.UserProfile
|
||||
if (model != null)
|
||||
model.RefreshCommand = new Command(() =>
|
||||
{
|
||||
DataManager.Current.RemoteFiles.Execute(null);
|
||||
var item = DataManager.Current.RemoteFiles.CurrentItem;
|
||||
DataManager.Instance.RemoteFiles.Execute(null);
|
||||
var item = DataManager.Instance.RemoteFiles.CurrentItem;
|
||||
if (item != null)
|
||||
model.InnerModel = item;
|
||||
// this.dirlist.EndRefresh();
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
<StackLayout VisualElement.IsVisible="{Binding IsAPerformer}">
|
||||
<StackLayout Orientation="Horizontal" VerticalOptions="Start"
|
||||
VisualElement.IsVisible="{Binding UserIsPro}" >
|
||||
VisualElement.IsVisible="{Binding IsAPerformer}" >
|
||||
<Label Text="Ne recevoir de demande de devis que de la part de professionnels uniquement" />
|
||||
<Switch HorizontalOptions="End" IsToggled="{Binding AllowProBookingOnly, Mode=TwoWay}"/>
|
||||
</StackLayout>
|
||||
|
@ -1,5 +1,7 @@
|
||||
|
||||
using BookAStar.ViewModels.UserProfile;
|
||||
using Plugin.Media;
|
||||
using Plugin.Media.Abstractions;
|
||||
using System;
|
||||
|
||||
using Xamarin.Forms;
|
||||
@ -13,10 +15,35 @@ namespace BookAStar.Pages.UserProfile
|
||||
InitializeComponent();
|
||||
AvatarButton.Clicked += AvatarButton_Clicked;
|
||||
}
|
||||
|
||||
private void AvatarButton_Clicked (object sender, EventArgs e)
|
||||
public UserProfilePage(UserProfileViewModel model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeComponent();
|
||||
AvatarButton.Clicked += AvatarButton_Clicked;
|
||||
BindingContext = model;
|
||||
}
|
||||
private async void AvatarButton_Clicked (object sender, EventArgs e)
|
||||
{
|
||||
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
|
||||
{
|
||||
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
|
||||
{
|
||||
Directory = "Avatars",
|
||||
Name = "me.jpg"
|
||||
});
|
||||
|
||||
if (file == null)
|
||||
return;
|
||||
// ImageSource.FromFile(file.Path);
|
||||
/* ImageSource.FromStream(() =>
|
||||
{
|
||||
var stream = file.GetStream();
|
||||
file.Dispose();
|
||||
return stream;
|
||||
}); */
|
||||
}
|
||||
|
||||
public void OnManageFiles(object sender, EventArgs e)
|
||||
|
@ -1,6 +1,4 @@
|
||||
// Helpers/Settings.cs
|
||||
using BookAStar.Model;
|
||||
using BookAStar.Model.Auth.Account;
|
||||
using Newtonsoft.Json;
|
||||
using Plugin.Settings;
|
||||
using Plugin.Settings.Abstractions;
|
||||
@ -8,11 +6,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace BookAStar
|
||||
{
|
||||
using Model.Social;
|
||||
using Model.Auth.Account;
|
||||
using Data;
|
||||
|
||||
/// <summary>
|
||||
/// This is the Settings static class that can be used in your Core solution or in any
|
||||
@ -32,7 +31,7 @@ namespace BookAStar
|
||||
|
||||
#region Setting Constants
|
||||
public static readonly string SettingsDefault = string.Empty;
|
||||
public static readonly string EntityDataSettingsPrefix = "Ed";
|
||||
public static readonly string EntityDataSettingsPrefix = Constants.YavscApiUrl;
|
||||
private const string userNameKey = "user_id";
|
||||
private const string PushNotificationsKey = "pushNotifs";
|
||||
private const string AllowGPSUsageKey = "allowGPSUsage";
|
||||
@ -75,23 +74,13 @@ namespace BookAStar
|
||||
}
|
||||
}
|
||||
public const string bookQueryNotificationsKey = "BookQueryNotifications";
|
||||
public static BookQueryData[] GetBookQueryNotifications()
|
||||
public static BookQuery[] GetBookQueryNotifications()
|
||||
{
|
||||
// Do not return any null List
|
||||
var json = AppSettings.GetValueOrDefault<string>(bookQueryNotificationsKey);
|
||||
if (!string.IsNullOrWhiteSpace(json))
|
||||
return JsonConvert.DeserializeObject<BookQueryData[]>(json);
|
||||
return new BookQueryData[] { };
|
||||
}
|
||||
|
||||
public static BookQueryData[] AddBookQueryNotification(BookQueryData query)
|
||||
{
|
||||
var existing = new List<BookQueryData>(GetBookQueryNotifications());
|
||||
existing.Add(query);
|
||||
var result = existing.ToArray();
|
||||
AppSettings.AddOrUpdateValue(bookQueryNotificationsKey,
|
||||
JsonConvert.SerializeObject(result));
|
||||
return result;
|
||||
return JsonConvert.DeserializeObject<BookQuery[]>(json);
|
||||
return new BookQuery[] { };
|
||||
}
|
||||
|
||||
public static string GoogleRegId
|
||||
@ -104,7 +93,7 @@ namespace BookAStar
|
||||
// Inform the server of it.
|
||||
if (oldregid != value)
|
||||
{
|
||||
App.CurrentApp.PostDeviceInfo();
|
||||
App.PostDeviceInfo();
|
||||
}
|
||||
}
|
||||
get { return AppSettings.GetValueOrDefault<string>(GoogleRegIdKey); }
|
||||
@ -155,15 +144,15 @@ namespace BookAStar
|
||||
{
|
||||
if (olduserid != value.Id)
|
||||
{
|
||||
App.CurrentApp.PostDeviceInfo();
|
||||
App.PostDeviceInfo();
|
||||
if (UserChanged!=null)
|
||||
UserChanged.Invoke(App.CurrentApp, new EventArgs());
|
||||
UserChanged.Invoke(App.Current, new EventArgs());
|
||||
}
|
||||
}
|
||||
else if (olduserid != null)
|
||||
{
|
||||
if (UserChanged != null)
|
||||
UserChanged.Invoke(App.CurrentApp, new EventArgs());
|
||||
UserChanged.Invoke(App.Current, new EventArgs());
|
||||
// TODO else Unregister this device
|
||||
}
|
||||
}
|
||||
@ -171,21 +160,34 @@ namespace BookAStar
|
||||
|
||||
public static event EventHandler<EventArgs> UserChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Saves the given user account in the account list.
|
||||
/// An existent presenting the same Id will be dropped.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
public static void SaveUser(User user)
|
||||
{
|
||||
var existent = AccountList.FirstOrDefault(u => u.UserName == user.UserName);
|
||||
var existent = AccountList.FirstOrDefault(u => u.Id == user.Id);
|
||||
if (existent != null)
|
||||
AccountList.Remove(existent);
|
||||
AccountList.Add(user);
|
||||
var json = JsonConvert.SerializeObject(AccountList.ToArray());
|
||||
AppSettings.AddOrUpdateValue(UserListsKey, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an account connection info, given its name
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
public static User GetUser(string username)
|
||||
{
|
||||
return AccountList.FirstOrDefault(a => a.UserName == username);
|
||||
}
|
||||
|
||||
// FIXME real time usage
|
||||
/// <summary>
|
||||
/// Enables/disables push notifications
|
||||
/// </summary>
|
||||
public static bool PushNotifications
|
||||
{
|
||||
get
|
||||
@ -203,6 +205,10 @@ namespace BookAStar
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME real time usage
|
||||
/// <summary>
|
||||
/// Enables/disables GPS usage
|
||||
/// </summary>
|
||||
public static bool AllowGPSUsage
|
||||
{
|
||||
get
|
||||
@ -218,7 +224,11 @@ namespace BookAStar
|
||||
value);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO make it a server side user's parameter
|
||||
/// <summary>
|
||||
/// Only allow professionals to ask for user's services
|
||||
/// </summary>
|
||||
public static bool AllowProBookingOnly
|
||||
{
|
||||
get
|
||||
|
209
BookAStar/BookAStar/Strings.Designer.cs
generated
209
BookAStar/BookAStar/Strings.Designer.cs
generated
@ -61,6 +61,60 @@ 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 à Bloquer cet utilisateur.
|
||||
/// </summary>
|
||||
public static string BlockThisUser {
|
||||
get {
|
||||
return ResourceManager.GetString("BlockThisUser", 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 à Restreindre la demande aux clients professionnels.
|
||||
/// </summary>
|
||||
public static string ClientProRequest {
|
||||
get {
|
||||
return ResourceManager.GetString("ClientProRequest", 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>
|
||||
/// Recherche une chaîne localisée semblable à Décliner cette proposition (envoyer un refus, et archiver la demande).
|
||||
/// </summary>
|
||||
public static string DeclineQuery {
|
||||
get {
|
||||
return ResourceManager.GetString("DeclineQuery", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une chaîne localisée semblable à Faire un devis.
|
||||
/// </summary>
|
||||
@ -70,6 +124,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>
|
||||
/// Recherche une chaîne localisée semblable à Editer le devis.
|
||||
/// </summary>
|
||||
@ -79,6 +142,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>
|
||||
/// Recherche une chaîne localisée semblable à Star.
|
||||
/// </summary>
|
||||
@ -97,6 +169,51 @@ namespace BookAStar {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une chaîne localisée semblable à Géographiquement proche.
|
||||
/// </summary>
|
||||
public static string GeographicalyNear {
|
||||
get {
|
||||
return ResourceManager.GetString("GeographicalyNear", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
@ -115,6 +232,60 @@ 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 à Profile professionnel.
|
||||
/// </summary>
|
||||
public static string Profprof {
|
||||
get {
|
||||
return ResourceManager.GetString("Profprof", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une chaîne localisée semblable à Rechercher un artiste.
|
||||
/// </summary>
|
||||
public static string SearchForAPro {
|
||||
get {
|
||||
return ResourceManager.GetString("SearchForAPro", 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>
|
||||
/// Recherche une chaîne localisée semblable à Incontournable.
|
||||
/// </summary>
|
||||
@ -134,12 +305,48 @@ namespace BookAStar {
|
||||
}
|
||||
|
||||
/// <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 à Comptes utilisateur.
|
||||
/// </summary>
|
||||
public static string UserAccounts {
|
||||
get {
|
||||
return ResourceManager.GetString("UserAccounts", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une chaîne localisée semblable à Voir les devis validés.
|
||||
/// </summary>
|
||||
public static string ViewEstimate {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewEstimate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une chaîne localisée semblable à Vos fichiers .
|
||||
/// </summary>
|
||||
public static string YourFiles {
|
||||
get {
|
||||
return ResourceManager.GetString("YourFiles", 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,12 +117,27 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AlreadyExecuting" xml:space="preserve">
|
||||
<value>Une execution est déjà en cours</value>
|
||||
</data>
|
||||
<data name="CancelValidation" xml:space="preserve">
|
||||
<value>Annuler la validation</value>
|
||||
</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">
|
||||
<value>Faire un devis</value>
|
||||
</data>
|
||||
<data name="DonotsignEstimate" xml:space="preserve">
|
||||
<value>Valider le devis sans signer</value>
|
||||
</data>
|
||||
<data name="EditEstimate" xml:space="preserve">
|
||||
<value>Editer le devis</value>
|
||||
</data>
|
||||
<data name="ENoRemoteEntity" xml:space="preserve">
|
||||
<value>Erreur d'accès aux données distantes</value>
|
||||
</data>
|
||||
<data name="FiveStars" xml:space="preserve">
|
||||
<value>Star</value>
|
||||
<comment>Da star, da one</comment>
|
||||
@ -137,6 +152,18 @@
|
||||
<data name="OneStar" xml:space="preserve">
|
||||
<value>Étoile montante</value>
|
||||
</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">
|
||||
<value>Signer</value>
|
||||
</data>
|
||||
<data name="SignOrNot" xml:space="preserve">
|
||||
<value>Signer le devis?</value>
|
||||
</data>
|
||||
<data name="ThreeStars" xml:space="preserve">
|
||||
<value>Incontournable</value>
|
||||
</data>
|
||||
@ -144,6 +171,48 @@
|
||||
<value>À ne manquer sous aucun prétexte</value>
|
||||
</data>
|
||||
<data name="ViewEstimate" xml:space="preserve">
|
||||
<value>Voir le devis</value>
|
||||
<value>Voir les devis validés</value>
|
||||
</data>
|
||||
<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>
|
||||
<data name="YourFiles" xml:space="preserve">
|
||||
<value>Vos fichiers </value>
|
||||
</data>
|
||||
<data name="Profprof" xml:space="preserve">
|
||||
<value>Profile professionnel</value>
|
||||
</data>
|
||||
<data name="ClientProRequest" xml:space="preserve">
|
||||
<value>Restreindre la demande aux clients professionnels</value>
|
||||
</data>
|
||||
<data name="UserAccounts" xml:space="preserve">
|
||||
<value>Comptes utilisateur</value>
|
||||
</data>
|
||||
<data name="BlockThisUser" xml:space="preserve">
|
||||
<value>Bloquer cet utilisateur</value>
|
||||
</data>
|
||||
<data name="DeclineQuery" xml:space="preserve">
|
||||
<value>Décliner cette proposition (envoyer un refus, et archiver la demande)</value>
|
||||
</data>
|
||||
<data name="GeographicalyNear" xml:space="preserve">
|
||||
<value>Géographiquement proche</value>
|
||||
</data>
|
||||
<data name="SearchForAPro" xml:space="preserve">
|
||||
<value>Rechercher un artiste</value>
|
||||
</data>
|
||||
</root>
|
@ -1,29 +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
|
||||
{
|
||||
private LocalState state;
|
||||
public LocalState State {
|
||||
get
|
||||
{
|
||||
return state;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.SetProperty<LocalState>(ref state, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +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 ?? new BillingLine();
|
||||
// sets durationValue & durationUnit
|
||||
count = data.Count;
|
||||
description = data.Description;
|
||||
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();
|
||||
}
|
||||
|
||||
Duration = data.Duration;
|
||||
unitaryCostText = data.UnitaryCost.ToString("G", CultureInfo.InvariantCulture);
|
||||
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;
|
||||
@ -33,7 +62,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
set
|
||||
{
|
||||
SetProperty<int>(ref count, value);
|
||||
data.Count = count;
|
||||
Data.Count = count;
|
||||
}
|
||||
}
|
||||
private string description;
|
||||
@ -47,9 +76,10 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
set
|
||||
{
|
||||
SetProperty<string>(ref description, value);
|
||||
data.Description = description;
|
||||
Data.Description = description;
|
||||
}
|
||||
}
|
||||
|
||||
decimal unitaryCost;
|
||||
public decimal UnitaryCost
|
||||
{
|
||||
@ -61,7 +91,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
set
|
||||
{
|
||||
SetProperty<decimal>(ref unitaryCost, value);
|
||||
data.UnitaryCost = unitaryCost;
|
||||
Data.UnitaryCost = unitaryCost;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +106,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
set
|
||||
{
|
||||
SetProperty<int>(ref durationValue, value, "DurationValue");
|
||||
data.Duration = this.Duration;
|
||||
Data.Duration = this.Duration;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +155,6 @@ pour décrire la quantité de travail associée à ce type de service")]
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand ValidateCommand { set; get; }
|
||||
|
||||
public TimeSpan Duration
|
||||
{
|
||||
|
@ -5,18 +5,24 @@ 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<BookQueryData> Queries
|
||||
public ObservableCollection<BookQueryViewModel> Queries
|
||||
{
|
||||
get
|
||||
{
|
||||
return DataManager.Current.BookQueries;
|
||||
return queries;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,20 +6,22 @@ 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;
|
||||
|
||||
class BookQueryViewModel : ViewModel, IBookQueryData
|
||||
public class BookQueryViewModel : ViewModel, IBookQueryData
|
||||
{
|
||||
public BookQueryViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
public BookQueryViewModel(BookQueryData data)
|
||||
public BookQueryViewModel(BookQuery data)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
Client=data.Client;
|
||||
@ -28,19 +30,33 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
Previsionnal = data.Previsionnal;
|
||||
Id = data.Id;
|
||||
estimates = new ObservableCollection<Estimate>(
|
||||
DataManager.Current.Estimates.Where(
|
||||
DataManager.Instance.Estimates.Where(
|
||||
e => e.Query.Id == Id
|
||||
));
|
||||
this.data = data;
|
||||
}
|
||||
private BookQueryData data;
|
||||
public BookQueryData 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; }
|
||||
@ -49,7 +65,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
{
|
||||
get
|
||||
{
|
||||
return DataManager.Current.EstimationCache.LocalGet(this.Id);
|
||||
return DataManager.Instance.EstimationCache.LocalGet(this.Id);
|
||||
}
|
||||
}
|
||||
private ObservableCollection<Estimate> estimates;
|
||||
|
@ -1,55 +1,78 @@
|
||||
using System.Collections.Generic;
|
||||
using BookAStar.Model.Workflow;
|
||||
using System.Collections.ObjectModel;
|
||||
using BookAStar.Model;
|
||||
using Xamarin.Forms;
|
||||
using BookAStar.Data;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
{
|
||||
public class EditEstimateViewModel : EditingViewModel
|
||||
using Model;
|
||||
using Model.Workflow;
|
||||
using Model.Social;
|
||||
using Validation;
|
||||
public class EditEstimateViewModel : EditingViewModel<Estimate>
|
||||
{
|
||||
/// <summary>
|
||||
/// For deserialization
|
||||
/// </summary>
|
||||
public EditEstimateViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
/// <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)
|
||||
public EditEstimateViewModel(Estimate data) : base(data)
|
||||
{
|
||||
Data = 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 = new List<BillingLine>( Bill );
|
||||
Data.Bill = Bill.Select(l => l.Data).ToList();
|
||||
NotifyPropertyChanged("FormattedTotal");
|
||||
NotifyPropertyChanged("Bill");
|
||||
NotifyPropertyChanged("ViewModelState");
|
||||
}
|
||||
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<BillingLine>(data.Bill);
|
||||
Bill.CollectionChanged += Bill_CollectionChanged;
|
||||
Title = Data.Title;
|
||||
Description = Data.Description;
|
||||
NotifyPropertyChanged("FormattedTotal");
|
||||
NotifyPropertyChanged("Query");
|
||||
NotifyPropertyChanged("CLient");
|
||||
} }
|
||||
|
||||
[JsonIgnore]
|
||||
public ObservableCollection<string> AttachedFiles
|
||||
@ -64,7 +87,7 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public ObservableCollection<BillingLine> Bill
|
||||
public ObservableCollection<BillingLineViewModel> Bill
|
||||
{
|
||||
get; protected set;
|
||||
}
|
||||
@ -107,25 +130,27 @@ namespace BookAStar.ViewModels.EstimateAndBilling
|
||||
public ClientProviderInfo Client { get { return Data.Client; } }
|
||||
|
||||
[JsonIgnore]
|
||||
public BookQueryData Query { get { return Data.Query; } }
|
||||
public BookQuery Query { get { return Data.Query; } }
|
||||
|
||||
[JsonIgnore]
|
||||
public FormattedString FormattedTotal
|
||||
{
|
||||
get
|
||||
{
|
||||
OnPlatform<Font> lfs = (OnPlatform<Font>)App.Current.Resources["LargeFontSize"];
|
||||
OnPlatform<Color> etc = (OnPlatform<Color>)App.Current.Resources["EmphasisTextColor"];
|
||||
/*
|
||||
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.Android ,
|
||||
FontSize = (double) lfs.Android.FontSize },
|
||||
new Span { Text = "€", FontSize = (double) lfs.Android.FontSize }
|
||||
ForegroundColor = etc,
|
||||
FontSize = mfs },
|
||||
new Span { Text = "€", FontSize = mfs }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
14
BookAStar/BookAStar/ViewModels/HomeViewModel.cs
Normal file
14
BookAStar/BookAStar/ViewModels/HomeViewModel.cs
Normal 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; }
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
196
BookAStar/BookAStar/ViewModels/Messaging/ChatUserInfo.cs
Normal file
196
BookAStar/BookAStar/ViewModels/Messaging/ChatUserInfo.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,27 +7,15 @@ using XLabs.Forms.Mvvm;
|
||||
namespace BookAStar.ViewModels.Messaging
|
||||
{
|
||||
using Data;
|
||||
using Model;
|
||||
using Model.Social.Chat;
|
||||
using Model.Social.Messaging;
|
||||
|
||||
class ChatViewModel: ViewModel
|
||||
public class ChatViewModel: ViewModel
|
||||
{
|
||||
public ObservableCollection<ChatMessage> Messages { get; set; }
|
||||
public ObservableCollection<ChatMessage> Notifs { get; set; }
|
||||
public ObservableCollection<ChatMessage> PVs { get; set; }
|
||||
public ObservableCollection<ClientProviderInfo> Contacts { get; set; }
|
||||
private string chatUser;
|
||||
public string ChatUser
|
||||
{
|
||||
get
|
||||
{
|
||||
return chatUser;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty<string>(ref chatUser, value);
|
||||
}
|
||||
}
|
||||
public ChatUserCollection ChatUsers { get; set; }
|
||||
|
||||
private ConnectionState state;
|
||||
public ConnectionState State
|
||||
{
|
||||
@ -40,8 +28,7 @@ namespace BookAStar.ViewModels.Messaging
|
||||
MainSettings.UserChanged += MainSettings_UserChanged;
|
||||
Messages = new ObservableCollection<ChatMessage>();
|
||||
Notifs = new ObservableCollection<ChatMessage>();
|
||||
PVs = DataManager.Current.PrivateMessages;
|
||||
Contacts = DataManager.Current.Contacts;
|
||||
ChatUsers = DataManager.Instance.ChatUsers;
|
||||
App.ChatHubProxy.On<string, string>("addMessage", (n, m) =>
|
||||
{
|
||||
Messages.Add(new ChatMessage
|
||||
@ -54,45 +41,53 @@ namespace BookAStar.ViewModels.Messaging
|
||||
|
||||
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.
|
||||
// From now, don't log anonymous
|
||||
if (!string.IsNullOrEmpty(userName))
|
||||
if (string.IsNullOrEmpty(userName))
|
||||
{
|
||||
Notifs.Add(new ChatMessage
|
||||
{
|
||||
Message = eventId,
|
||||
SenderId = userName,
|
||||
Date = DateTime.Now
|
||||
});
|
||||
if (eventId == "connected")
|
||||
OnUserConnected(cxId, userName);
|
||||
else if (eventId == "disconnected")
|
||||
OnUserDisconnected(userName);
|
||||
msg.SenderId = $"({cxId})";
|
||||
}
|
||||
Notifs.Add(msg);
|
||||
if (eventId == "connected")
|
||||
OnUserConnected(cxId, userName);
|
||||
else if (eventId == "disconnected")
|
||||
OnUserDisconnected(cxId, userName);
|
||||
});
|
||||
ChatUser = MainSettings.UserName;
|
||||
}
|
||||
|
||||
private void OnUserConnected(string cxId, string userName)
|
||||
{
|
||||
var user = Contacts.SingleOrDefault(
|
||||
var user = ChatUsers.SingleOrDefault(
|
||||
c => c.UserName == userName);
|
||||
if (user != null)
|
||||
user.ChatHubConnectionId = cxId;
|
||||
if (user == null)
|
||||
{
|
||||
user = new ChatUserInfo {
|
||||
UserName = userName
|
||||
};
|
||||
ChatUsers.Add(user);
|
||||
}
|
||||
user.OnConnected(cxId);
|
||||
}
|
||||
|
||||
private void OnUserDisconnected (string userName)
|
||||
private void OnUserDisconnected (string cxId, string userName)
|
||||
{
|
||||
var user = Contacts.SingleOrDefault(
|
||||
var user = ChatUsers.SingleOrDefault(
|
||||
c => c.UserName == userName);
|
||||
if (user != null)
|
||||
user.ChatHubConnectionId = null;
|
||||
if (user == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
user.OnDisconnected(cxId);
|
||||
}
|
||||
|
||||
private void MainSettings_UserChanged(object sender, EventArgs e)
|
||||
{
|
||||
ChatUser = MainSettings.UserName;
|
||||
}
|
||||
|
||||
private void ChatHubConnection_StateChanged(StateChange obj)
|
||||
|
@ -1,6 +1,6 @@
|
||||
using XLabs.Forms.Mvvm;
|
||||
|
||||
namespace BookAStar.Model.UI
|
||||
namespace BookAStar.ViewModels
|
||||
{
|
||||
internal class PageState
|
||||
{
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user