This commit is contained in:
Trevi Awater
2022-06-13 15:51:05 +02:00
parent 9e6b1136ea
commit aa6fa75136
10 changed files with 135 additions and 34 deletions

View File

@@ -27,7 +27,7 @@
<key>CFBundleIdentifier</key>
<string>nl.resoftware.pocketgraph</string>
<key>CFBundleVersion</key>
<string>1.0.2</string>
<string>1.0.3</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>CFBundleName</key>

View File

@@ -59,5 +59,22 @@ namespace Xamarin.Neo4j.Managers
await SaveConnectionStrings(connectionStrings);
}
public static async Task UpdateConnectionString(Guid id, Neo4jConnectionString connectionString)
{
var connectionStrings = await GetConnectionStrings();
var connectionStringToUpdate = connectionStrings.FirstOrDefault(cs => cs.Id == id);
if (connectionStringToUpdate == null)
return;
connectionStringToUpdate.Scheme = connectionString.Scheme;
connectionStringToUpdate.Host = connectionString.Host;
connectionStringToUpdate.Username = connectionString.Username;
connectionStringToUpdate.Password = connectionString.Password;
await SaveConnectionStrings(connectionStrings);
}
}
}

View File

@@ -21,23 +21,27 @@ namespace Xamarin.Neo4j.Models
public string Host { get; set; }
public string Scheme { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public Tuple<string, bool, bool> ParseHost()
{
if (Host.StartsWith("neo4j://"))
return new Tuple<string, bool, bool>(Host, false, false);
var fullHost = Scheme + Host;
if (Host.StartsWith("bolt://"))
return new Tuple<string, bool, bool>(Host.Replace("bolt://", "neo4j://"), false, false);
if (fullHost.StartsWith("neo4j://"))
return new Tuple<string, bool, bool>(fullHost, false, false);
if (Host.StartsWith("neo4j+s://"))
return new Tuple<string, bool, bool>(Host.Replace("neo4j+s://", "neo4j://"), true, false);
if (fullHost.StartsWith("bolt://"))
return new Tuple<string, bool, bool>(fullHost.Replace("bolt://", "neo4j://"), false, false);
if (Host.StartsWith("neo4j+ssc://"))
return new Tuple<string, bool, bool>(Host.Replace("neo4j+ssc://", "neo4j://"), true, true);
if (fullHost.StartsWith("neo4j+s://"))
return new Tuple<string, bool, bool>(fullHost.Replace("neo4j+s://", "neo4j://"), true, false);
if (fullHost.StartsWith("neo4j+ssc://"))
return new Tuple<string, bool, bool>(fullHost.Replace("neo4j+ssc://", "neo4j://"), true, true);
throw new NotSupportedException("Unknown protocol.");
}

View File

@@ -7,6 +7,22 @@
<ContentPage.Content>
<ScrollView>
<StackLayout Padding="24" Spacing="12">
<StackLayout Spacing="4">
<Label Text="Scheme:" FontAttributes="Bold" FontSize="Small" />
<Picker SelectedItem="{Binding Scheme}">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>neo4j://</x:String>
<x:String>neo4j+s://</x:String>
<x:String>neo4j+ssc://</x:String>
<x:String>bolt://</x:String>
<x:String>bolt+s://</x:String>
<x:String>bolt+ssc://</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
</StackLayout>
<StackLayout Spacing="4">
<Label Text="Host:" FontAttributes="Bold" FontSize="Small" />
<Entry Text="{Binding Host}" />

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Xamarin.Neo4j.Models;
using Xamarin.Neo4j.ViewModels;
namespace Xamarin.Neo4j.Pages
@@ -13,11 +14,11 @@ namespace Xamarin.Neo4j.Pages
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AddConnectionPage : ContentPage
{
public AddConnectionPage()
public AddConnectionPage(Neo4jConnectionString neo4JConnectionString = null)
{
InitializeComponent();
BindingContext = new AddConnectionViewModel(Navigation);
BindingContext = new AddConnectionViewModel(Navigation, neo4JConnectionString);
}
}
}

View File

@@ -45,7 +45,8 @@
<DataTemplate>
<controls:ConnectionCell IsActive="{Binding ., Converter={StaticResource isActiveConnection}}">
<controls:ConnectionCell.ContextActions>
<MenuItem Text="Delete" Command="{Binding BindingContext.Commands[DeleteConnectionString], Source={x:Reference connectionsPage} }" CommandParameter="{Binding .}" IsDestructive="true" />
<MenuItem Text="Edit" Command="{Binding BindingContext.Commands[EditConnectionString], Source={x:Reference connectionsPage}}" CommandParameter="{Binding .}" />
<MenuItem Text="Delete" Command="{Binding BindingContext.Commands[DeleteConnectionString], Source={x:Reference connectionsPage}}" CommandParameter="{Binding .}" IsDestructive="true" />
</controls:ConnectionCell.ContextActions>
</controls:ConnectionCell>
</DataTemplate>

View File

@@ -34,7 +34,7 @@ namespace Xamarin.Neo4j.Services
private BoltGraphClient GraphClient { get; set; }
public async Task<bool> EstablishConnection(Neo4jConnectionString connectionString)
public async Task<Tuple<bool, string>> EstablishConnection(Neo4jConnectionString connectionString)
{
try
{
@@ -54,22 +54,32 @@ namespace Xamarin.Neo4j.Services
await GraphClient.ConnectAsync();
}
catch (ServiceUnavailableException)
catch (ServiceUnavailableException e)
{
return false;
return new Tuple<bool, string>(false, e.Message);
}
catch (AuthenticationException)
catch (AuthenticationException e)
{
return false;
return new Tuple<bool, string>(false, e.Message);
}
catch (UriFormatException)
catch (SecurityException e)
{
return false;
return new Tuple<bool, string>(false, e.Message);
}
return true;
catch (UriFormatException e)
{
return new Tuple<bool, string>(false, e.Message);
}
catch (NotSupportedException e)
{
return new Tuple<bool, string>(false, e.Message);
}
return new Tuple<bool, string>(true, "Connection was successful!");
}
public async Task<List<Database>> LoadDatabases()

View File

@@ -25,15 +25,21 @@ namespace Xamarin.Neo4j.ViewModels
{
public class AddConnectionViewModel : ViewModelBase, INotifyPropertyChanged
{
private string _host, _username, _password;
private Guid? _id;
private string _scheme, _host, _username, _password;
private readonly Neo4jService _neo4jService;
public event PropertyChangedEventHandler PropertyChanged;
public AddConnectionViewModel(INavigation navigation) : base(navigation)
public AddConnectionViewModel(INavigation navigation, Neo4jConnectionString neo4JConnectionString = null) : base(navigation)
{
InitializeDefaultValues();
if (neo4JConnectionString == null)
InitializeDefaultValues();
else
InitializeValues(neo4JConnectionString);
_neo4jService = DependencyService.Resolve<Neo4jService>();
@@ -41,23 +47,29 @@ namespace Xamarin.Neo4j.ViewModels
{
var connectionString = BuildConnectionString();
var couldConnect = await _neo4jService.EstablishConnection(connectionString);
var (_, message) = await _neo4jService.EstablishConnection(connectionString);
await UserDialogs.Instance.AlertAsync(couldConnect ? "Connection successful." : "Connection failed.");
await UserDialogs.Instance.AlertAsync(message);
}));
Commands.Add("Save", new Command(async () =>
{
var connectionString = BuildConnectionString();
var namePromptResult = await UserDialogs.Instance.PromptAsync("How do you want to name this connection?", "Save Connection", "Save", "Cancel");
if (_id.HasValue)
await ConnectionStringManager.UpdateConnectionString(_id.Value, connectionString);
if (!namePromptResult.Ok || string.IsNullOrWhiteSpace(namePromptResult.Value))
return;
else
{
var namePromptResult = await UserDialogs.Instance.PromptAsync("How do you want to name this connection?", "Save Connection", "Save", "Cancel");
connectionString.Name = namePromptResult.Value;
if (!namePromptResult.Ok || string.IsNullOrWhiteSpace(namePromptResult.Value))
return;
await ConnectionStringManager.AddConnectionString(connectionString);
connectionString.Name = namePromptResult.Value;
await ConnectionStringManager.AddConnectionString(connectionString);
}
await Navigation.PopAsync();
}));
@@ -66,19 +78,30 @@ namespace Xamarin.Neo4j.ViewModels
{
var connectionString = BuildConnectionString();
var couldConnect = await _neo4jService.EstablishConnection(connectionString);
var (couldConnect, message) = await _neo4jService.EstablishConnection(connectionString);
if (couldConnect)
await Navigation.PushAsync(new SessionPage(connectionString));
else
await UserDialogs.Instance.AlertAsync( "Connection failed.");
await UserDialogs.Instance.AlertAsync(message);
}));
}
private void InitializeValues(Neo4jConnectionString neo4JConnectionString)
{
_id = neo4JConnectionString.Id;
Scheme = neo4JConnectionString.Scheme;
Host = neo4JConnectionString.Host;
Username = neo4JConnectionString.Username;
Password = neo4JConnectionString.Password;
}
private void InitializeDefaultValues()
{
Username = "neo4j";
Scheme = "neo4j://";
}
[NotifyPropertyChangedInvocator]
@@ -92,6 +115,7 @@ namespace Xamarin.Neo4j.ViewModels
return new Neo4jConnectionString
{
Id = Guid.NewGuid(),
Scheme = Scheme,
Host = Host,
Username = Username,
Password = Password
@@ -100,6 +124,18 @@ namespace Xamarin.Neo4j.ViewModels
#region Bindable Properties
public string Scheme
{
get => _scheme;
set
{
_scheme = value;
OnPropertyChanged(nameof(Scheme));
}
}
public string Host
{
get => _host;

View File

@@ -32,6 +32,14 @@ namespace Xamarin.Neo4j.ViewModels
Navigation.PushAsync(new AddConnectionPage());
}));
Commands.Add("EditConnectionString", new Command(async (o) =>
{
if (!(o is Neo4jConnectionString neo4jConnectionString))
return;
await Navigation.PushAsync(new AddConnectionPage(neo4jConnectionString));
}));
Commands.Add("DeleteConnectionString", new Command(async (o) =>
{
if (!(o is Neo4jConnectionString neo4jConnectionString))

View File

@@ -7,6 +7,7 @@
// © Xamarin.Neo4j
//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
@@ -78,7 +79,14 @@ namespace Xamarin.Neo4j.ViewModels
private async void InitializeConnection(Neo4jConnectionString connectionString)
{
await _neo4jService.EstablishConnection(connectionString);
var (isConnected, message) = await _neo4jService.EstablishConnection(connectionString);
if (!isConnected)
{
await UserDialogs.Instance.AlertAsync(message);
return;
}
AvailableDatabases = await _neo4jService.LoadDatabases();