mirror of
https://github.com/awatertrevi/xamarin-neo4j.git
synced 2026-09-22 09:05:29 +00:00
Fix
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
// © Xamarin.Neo4j.iOS
|
||||
//
|
||||
|
||||
using CoreGraphics;
|
||||
using UIKit;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Platform.iOS;
|
||||
@@ -18,6 +19,31 @@ namespace Xamarin.Neo4j.iOS.CustomRenderers
|
||||
{
|
||||
public class QueryEditorRenderer : EditorRenderer
|
||||
{
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
|
||||
{
|
||||
base.OnElementChanged(e);
|
||||
|
||||
if (Control != null && Element != null)
|
||||
{
|
||||
var executeButton = new UIBarButtonItem("Execute", UIBarButtonItemStyle.Done, (sender, args) =>
|
||||
{
|
||||
if (Element is QueryEditor queryEditor)
|
||||
{
|
||||
queryEditor.RaiseExecuteClicked();
|
||||
|
||||
Control.ResignFirstResponder();
|
||||
}
|
||||
});
|
||||
|
||||
var toolbar = new UIToolbar(new CGRect(0.0f, 0.0f, Control.Frame.Size.Width, 44.0f));
|
||||
toolbar.Items = new[]
|
||||
{
|
||||
new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace),
|
||||
executeButton
|
||||
};
|
||||
|
||||
Control.InputAccessoryView = toolbar;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Xamarin.Neo4j.Controls
|
||||
{
|
||||
public double MaxHeight { get; set; }
|
||||
|
||||
public event EventHandler ExecuteClicked;
|
||||
|
||||
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
var sizeRequest = base.OnMeasure(widthConstraint, heightConstraint);
|
||||
@@ -27,5 +29,10 @@ namespace Xamarin.Neo4j.Controls
|
||||
|
||||
return new SizeRequest(new Size(sizeRequest.Request.Width, newHeight));
|
||||
}
|
||||
|
||||
public void RaiseExecuteClicked()
|
||||
{
|
||||
ExecuteClicked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Xamarin.Neo4j.Controls
|
||||
result = result.Replace("{{password}}", QueryResult.ConnectionString.Password);
|
||||
result = result.Replace("{{encryption}}", isEncrypted ? "ENCRYPTION_ON" : "ENCRYPTION_OFF");
|
||||
result = result.Replace("{{trust}}", ignoreTrust ? "TRUST_ALL_CERTIFICATES" : "TRUST_SYSTEM_CA_SIGNED_CERTIFICATES");
|
||||
result = result.Replace("{{query}}", QueryResult.Query);
|
||||
result = result.Replace("{{query}}", QueryResult.DisplayQuery);
|
||||
result = result.Replace("{{backgroundColor}}", App.Current.RequestedTheme == OSAppTheme.Dark ? "#292C31" : "#FFFFFF");
|
||||
|
||||
_neovisHtml = result;
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace Xamarin.Neo4j.Models
|
||||
|
||||
public string Query { get; set; }
|
||||
|
||||
public string DisplayQuery { get; set; }
|
||||
|
||||
public Neo4jConnectionString ConnectionString { get; set; }
|
||||
|
||||
public Dictionary<string, List<object>> Results { get; set; }
|
||||
|
||||
@@ -36,18 +36,18 @@
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<StackLayout VerticalOptions="FillAndExpand">
|
||||
<pancakeView:PancakeView BackgroundColor="White" CornerRadius="2" Padding="4" Margin="16">
|
||||
<pancakeView:PancakeView CornerRadius="2">
|
||||
<pancakeView:PancakeView.Border>
|
||||
<pancakeView:Border Thickness="2" Color="#d8e5f1" />
|
||||
</pancakeView:PancakeView.Border>
|
||||
|
||||
<controls:QueryEditor Text="{Binding Query}" MaxHeight="200" HorizontalOptions="FillAndExpand" AutoSize="TextChanges" />
|
||||
<controls:QueryEditor Text="{Binding Query}" ExecuteClicked="ExecuteQuery" MaxHeight="200" HorizontalOptions="FillAndExpand" AutoSize="TextChanges" />
|
||||
</pancakeView:PancakeView>
|
||||
</pancakeView:PancakeView>
|
||||
|
||||
<CollectionView x:Name="resultsCollection" ItemsSource="{Binding QueryResults}">
|
||||
<CollectionView x:Name="resultsCollection" ItemsSource="{Binding QueryResults}" VerticalOptions="FillAndExpand">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:QueryResultView CloseRequested="CloseResultView" />
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using Xamarin.Neo4j.Models;
|
||||
@@ -15,6 +10,8 @@ namespace Xamarin.Neo4j.Pages
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class SessionPage : ContentPage
|
||||
{
|
||||
private bool _canCompleteEntry = true;
|
||||
|
||||
private SessionViewModel ViewModel => (SessionViewModel) BindingContext;
|
||||
|
||||
public SessionPage(Neo4jConnectionString connectionString, string initialQuery = null)
|
||||
@@ -38,5 +35,10 @@ namespace Xamarin.Neo4j.Pages
|
||||
{
|
||||
ViewModel.DeleteQueryResult(e.Data);
|
||||
}
|
||||
|
||||
private void ExecuteQuery(object sender, EventArgs e)
|
||||
{
|
||||
ViewModel.Commands["ExecuteQuery"].Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using Neo4jClient.Cypher;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Neo4j.Models;
|
||||
using Xamarin.Neo4j.Services;
|
||||
using Xamarin.Neo4j.Utilities;
|
||||
|
||||
[assembly: Dependency(typeof(Neo4jService))]
|
||||
|
||||
@@ -151,6 +152,7 @@ namespace Xamarin.Neo4j.Services
|
||||
Success = true,
|
||||
CanDisplayGraph = canDisplayGraph,
|
||||
Query = query,
|
||||
DisplayQuery = QueryHelper.TransformQuery(query),
|
||||
ConnectionString = connectionString,
|
||||
Results = results
|
||||
};
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// QueryHelper.cs
|
||||
//
|
||||
// Trevi Awater
|
||||
// 02-03-2024
|
||||
//
|
||||
// © Xamarin.Neo4j
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Xamarin.Neo4j.Utilities
|
||||
{
|
||||
public static class QueryHelper
|
||||
{
|
||||
public static string TransformQuery(string query)
|
||||
{
|
||||
// Check if there is a return statement, if not return the original query
|
||||
if (query.IndexOf("RETURN ", StringComparison.OrdinalIgnoreCase) <= 0)
|
||||
return query;
|
||||
|
||||
// This pattern is designed to match relationships with and without labels.
|
||||
// It captures the relationship direction and type, but not the existing label (if any).
|
||||
const string pattern = @"-\[:?(\w+)?\]->";
|
||||
var matches = Regex.Matches(query, pattern);
|
||||
|
||||
// Keep track of unique relationships to ensure they are returned
|
||||
var relationships = new List<string>();
|
||||
var relationshipCounter = 1;
|
||||
|
||||
var transformedQuery = query;
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
var newLabel = $"display_variable_{relationshipCounter++}"; // Generate a unique label for the relationship
|
||||
|
||||
// Replace the first occurrence of this match in the query with the new labeled version
|
||||
var oldPattern = match.Value;
|
||||
var newPattern = oldPattern.Replace("[:", $"[{newLabel}:").Replace("]->", "]->");
|
||||
var idx = transformedQuery.IndexOf(oldPattern);
|
||||
|
||||
if (idx != -1)
|
||||
{
|
||||
transformedQuery = transformedQuery.Substring(0, idx) + newPattern + transformedQuery.Substring(idx + oldPattern.Length);
|
||||
}
|
||||
|
||||
relationships.Add(newLabel);
|
||||
}
|
||||
|
||||
// Construct the new RETURN clause with the added relationships.
|
||||
if (relationships.Count > 0)
|
||||
{
|
||||
// Assuming there's always a RETURN statement to append to.
|
||||
var returnIndex = transformedQuery.LastIndexOf("RETURN ", StringComparison.OrdinalIgnoreCase);
|
||||
var returnClause = transformedQuery.Substring(returnIndex + "RETURN ".Length);
|
||||
var newReturnClause = string.Join(", ", relationships) + ", " + returnClause;
|
||||
|
||||
transformedQuery = transformedQuery.Substring(0, returnIndex) + "RETURN " + newReturnClause;
|
||||
}
|
||||
|
||||
return transformedQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user