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> <key>CFBundleIdentifier</key>
<string>nl.resoftware.pocketgraph</string> <string>nl.resoftware.pocketgraph</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0.2</string> <string>1.0.3</string>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@@ -59,5 +59,22 @@ namespace Xamarin.Neo4j.Managers
await SaveConnectionStrings(connectionStrings); 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 Host { get; set; }
public string Scheme { get; set; }
public string Username { get; set; } public string Username { get; set; }
public string Password { get; set; } public string Password { get; set; }
public Tuple<string, bool, bool> ParseHost() public Tuple<string, bool, bool> ParseHost()
{ {
if (Host.StartsWith("neo4j://")) var fullHost = Scheme + Host;
return new Tuple<string, bool, bool>(Host, false, false);
if (fullHost.StartsWith("neo4j://"))
return new Tuple<string, bool, bool>(fullHost, false, false);
if (Host.StartsWith("bolt://")) if (fullHost.StartsWith("bolt://"))
return new Tuple<string, bool, bool>(Host.Replace("bolt://", "neo4j://"), false, false); return new Tuple<string, bool, bool>(fullHost.Replace("bolt://", "neo4j://"), false, false);
if (Host.StartsWith("neo4j+s://")) if (fullHost.StartsWith("neo4j+s://"))
return new Tuple<string, bool, bool>(Host.Replace("neo4j+s://", "neo4j://"), true, false); return new Tuple<string, bool, bool>(fullHost.Replace("neo4j+s://", "neo4j://"), true, false);
if (Host.StartsWith("neo4j+ssc://")) if (fullHost.StartsWith("neo4j+ssc://"))
return new Tuple<string, bool, bool>(Host.Replace("neo4j+ssc://", "neo4j://"), true, true); return new Tuple<string, bool, bool>(fullHost.Replace("neo4j+ssc://", "neo4j://"), true, true);
throw new NotSupportedException("Unknown protocol."); throw new NotSupportedException("Unknown protocol.");
} }

View File

@@ -7,6 +7,22 @@
<ContentPage.Content> <ContentPage.Content>
<ScrollView> <ScrollView>
<StackLayout Padding="24" Spacing="12"> <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"> <StackLayout Spacing="4">
<Label Text="Host:" FontAttributes="Bold" FontSize="Small" /> <Label Text="Host:" FontAttributes="Bold" FontSize="Small" />
<Entry Text="{Binding Host}" /> <Entry Text="{Binding Host}" />

View File

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

View File

@@ -45,7 +45,8 @@
<DataTemplate> <DataTemplate>
<controls:ConnectionCell IsActive="{Binding ., Converter={StaticResource isActiveConnection}}"> <controls:ConnectionCell IsActive="{Binding ., Converter={StaticResource isActiveConnection}}">
<controls:ConnectionCell.ContextActions> <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.ContextActions>
</controls:ConnectionCell> </controls:ConnectionCell>
</DataTemplate> </DataTemplate>

View File

@@ -34,7 +34,7 @@ namespace Xamarin.Neo4j.Services
private BoltGraphClient GraphClient { get; set; } private BoltGraphClient GraphClient { get; set; }
public async Task<bool> EstablishConnection(Neo4jConnectionString connectionString) public async Task<Tuple<bool, string>> EstablishConnection(Neo4jConnectionString connectionString)
{ {
try try
{ {
@@ -54,22 +54,32 @@ namespace Xamarin.Neo4j.Services
await GraphClient.ConnectAsync(); 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() public async Task<List<Database>> LoadDatabases()

View File

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

View File

@@ -32,6 +32,14 @@ namespace Xamarin.Neo4j.ViewModels
Navigation.PushAsync(new AddConnectionPage()); 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) => Commands.Add("DeleteConnectionString", new Command(async (o) =>
{ {
if (!(o is Neo4jConnectionString neo4jConnectionString)) if (!(o is Neo4jConnectionString neo4jConnectionString))

View File

@@ -7,6 +7,7 @@
// © Xamarin.Neo4j // © Xamarin.Neo4j
// //
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
@@ -78,8 +79,15 @@ namespace Xamarin.Neo4j.ViewModels
private async void InitializeConnection(Neo4jConnectionString connectionString) 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(); AvailableDatabases = await _neo4jService.LoadDatabases();
if (!string.IsNullOrWhiteSpace(connectionString.Database)) if (!string.IsNullOrWhiteSpace(connectionString.Database))