Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion src/GraphNodeManagerViewExtension/GraphNodeManagerView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ private void ViewModel_RequestExportGraph(object parameter)
{
if (parameter == null) return;
var type = parameter.ToString();
var promptName = System.IO.Path.GetFileNameWithoutExtension(viewModel.CurrentWorkspace.FileName);
var workspaceFileName = viewModel.CurrentWorkspace?.FileName;
var rawPromptName = !string.IsNullOrWhiteSpace(workspaceFileName)
? System.IO.Path.GetFileNameWithoutExtension(workspaceFileName)
: viewModel.CurrentWorkspace?.Name;
Comment thread
QilongTang marked this conversation as resolved.
var promptName = SanitizePromptNameForFile(rawPromptName);

var filteredNodes = NodesInfoDataGrid.ItemsSource.Cast<GridNodeViewModel>().ToArray();

Expand All @@ -76,6 +80,42 @@ private void ViewModel_RequestExportGraph(object parameter)
}
}

private static string SanitizePromptNameForFile(string promptName)
{
const string fallbackName = "GraphNodes";

if (string.IsNullOrWhiteSpace(promptName))
{
return fallbackName;
}

var invalidChars = System.IO.Path.GetInvalidFileNameChars();
var sanitized = new string(promptName
.Select(ch => invalidChars.Contains(ch) ? '_' : ch)
.ToArray())
.Trim()
.TrimEnd('.');

if (string.IsNullOrWhiteSpace(sanitized))
{
return fallbackName;
}

var windowsReservedNames = new[]
{
"CON", "PRN", "AUX", "NUL",
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
};

if (windowsReservedNames.Contains(sanitized, StringComparer.OrdinalIgnoreCase))
{
return fallbackName;
}

return sanitized;
}

private void ViewModel_OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(GraphNodeManagerViewModel.IsAnyFilterOn))
Expand Down
23 changes: 23 additions & 0 deletions src/GraphNodeManagerViewExtension/Utilities/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Dynamo.Wpf.Utilities;
using Dynamo.Wpf.Properties;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Dynamo.GraphNodeManager.Utilities
{
Expand Down Expand Up @@ -48,6 +49,12 @@ public static void ExportToCSV(object exportObject, string promptName)

var csv = jsonToCSV(output);

if (csv.Count == 0)
{
File.WriteAllText(saveFileDialog.FileName, string.Empty);
return;
}

//write csv file into file stream
File.WriteAllLines(saveFileDialog.FileName, csv);
}
Expand Down Expand Up @@ -95,6 +102,17 @@ public static void ExportToJson(object exportObject, string promptName)
/// <returns></returns>
public static List<string> jsonToCSV(string jsonContent)
{
if (string.IsNullOrWhiteSpace(jsonContent))
{
return new List<string>();
}

var jsonToken = JToken.Parse(jsonContent);
if ((jsonToken is JArray jsonArray && !jsonArray.HasValues) || jsonToken.Type == JTokenType.Null)
{
return new List<string>();
}

XmlNode xml = JsonConvert.DeserializeXmlNode("{records:{record:" + jsonContent + "}}");
XmlDocument xmldoc = new XmlDocument();

Expand All @@ -104,6 +122,11 @@ public static List<string> jsonToCSV(string jsonContent)
DataSet dataSet = new DataSet();

dataSet.ReadXml(xmlReader);
if (dataSet.Tables.Count == 0)
{
return new List<string>();
}

var dataTable = dataSet.Tables[0];

//Datatable to CSV
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
Expand Down Expand Up @@ -235,6 +236,43 @@ public void ContainsEmptyListOrNullTest()
Assert.AreEqual(nullNodesCount, nullNodesImageCount);
}

[Test]
public void JsonToCsvWithEmptyArrayReturnsNoRows()
{
var csvLines = Dynamo.GraphNodeManager.Utilities.Utilities.jsonToCSV("[]");

Assert.IsNotNull(csvLines);
Assert.IsEmpty(csvLines);
}

[Test]
public void SanitizePromptNameForFile_ConvertsInvalidCharacters()
{
var method = typeof(GraphNodeManagerView).GetMethod(
"SanitizePromptNameForFile",
BindingFlags.NonPublic | BindingFlags.Static);

Assert.IsNotNull(method);

var sanitized = method.Invoke(null, new object[] { "Graph:Name*?" }) as string;

Assert.AreEqual("Graph_Name__", sanitized);
}

[Test]
public void SanitizePromptNameForFile_UsesFallbackForReservedNames()
{
var method = typeof(GraphNodeManagerView).GetMethod(
"SanitizePromptNameForFile",
BindingFlags.NonPublic | BindingFlags.Static);

Assert.IsNotNull(method);

var sanitized = method.Invoke(null, new object[] { "CON" }) as string;

Assert.AreEqual("GraphNodes", sanitized);
}

#region EnablePersistExtensions Tests
/// <summary>
/// Test if the Extension loads correctly when remembered
Expand Down
Loading