-
Notifications
You must be signed in to change notification settings - Fork 635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DYN-4034 : open file from json content #12671
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -144,6 +144,9 @@ internal static RecordableCommand Deserialize(XmlElement element) | |
case "OpenFileCommand": | ||
command = OpenFileCommand.DeserializeCore(element); | ||
break; | ||
case "OpenFileFromJsonCommand": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you use nameof? |
||
command = OpenFileFromJsonCommand.DeserializeCore(element); | ||
break; | ||
case "PausePlaybackCommand": | ||
command = PausePlaybackCommand.DeserializeCore(element); | ||
break; | ||
|
@@ -546,6 +549,83 @@ internal override void TrackAnalytics() | |
#endregion | ||
} | ||
|
||
/// <summary> | ||
/// A command to open a file from Json content. | ||
/// </summary> | ||
[DataContract] | ||
public class OpenFileFromJsonCommand : RecordableCommand | ||
{ | ||
#region Public Class Methods | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <param name="fileContents">The Json content of a file.</param> | ||
/// <param name="forceManualExecutionMode">Should the file be opened in manual execution mode?</param> | ||
public OpenFileFromJsonCommand(string fileContents, bool forceManualExecutionMode = false) | ||
{ | ||
FileContents = fileContents; | ||
ForceManualExecutionMode = forceManualExecutionMode; | ||
} | ||
|
||
internal static OpenFileFromJsonCommand DeserializeCore(XmlElement element) | ||
{ | ||
XmlElementHelper helper = new XmlElementHelper(element); | ||
string xmlFileContents = helper.ReadString("XmlFileContents"); | ||
return new OpenFileFromJsonCommand(xmlFileContents); | ||
} | ||
|
||
#endregion | ||
|
||
#region Public Command Properties | ||
|
||
[DataMember] | ||
internal string FileContents { get; private set; } | ||
internal bool ForceManualExecutionMode { get; private set; } | ||
private DynamoModel dynamoModel; | ||
|
||
#endregion | ||
|
||
#region Protected Overridable Methods | ||
|
||
protected override void ExecuteCore(DynamoModel dynamoModel) | ||
{ | ||
this.dynamoModel = dynamoModel; | ||
dynamoModel.OpenFileFromJsonImpl(this); | ||
} | ||
|
||
|
||
protected override void SerializeCore(XmlElement element) | ||
{ | ||
var helper = new XmlElementHelper(element); | ||
helper.SetAttribute("XmlFileContents", FileContents); | ||
} | ||
|
||
|
||
internal override void TrackAnalytics() | ||
{ | ||
// Log file open action and the number of nodes in the opened workspace | ||
Dynamo.Logging.Analytics.TrackFileOperationEvent( | ||
dynamoModel.CurrentWorkspace.Name, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we use something else here since Name will be an empty string ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this match the implementation/result for disk based file open? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, I see, the other uses filepath - maybe something that notes this is in memory open. |
||
Logging.Actions.Open, | ||
dynamoModel.CurrentWorkspace.Nodes.Count()); | ||
|
||
// If there are unresolved nodes in the opened workspace, log the node names and count | ||
var unresolvedNodes = dynamoModel.CurrentWorkspace.Nodes.OfType<DummyNode>(); | ||
if (unresolvedNodes != null && unresolvedNodes.Any()) | ||
{ | ||
Dynamo.Logging.Analytics.TrackEvent( | ||
Logging.Actions.Unresolved, | ||
Logging.Categories.NodeOperations, | ||
unresolvedNodes.Select(n => string.Format("{0}:{1}", n.LegacyAssembly, n.LegacyFullName)) | ||
.Aggregate((x, y) => string.Format("{0}, {1}", x, y)), | ||
unresolvedNodes.Count()); | ||
} | ||
} | ||
|
||
#endregion | ||
} | ||
|
||
/// <summary> | ||
/// A command used to execute or cancel execution. | ||
/// </summary> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,7 @@ public bool HasPendingTasks | |
} | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
#region Private Class Helper Methods | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -173,6 +173,7 @@ public void WorkspaceActualSize(double width, double height) | |||
|
||||
private WorkspaceViewModel currentWorkspaceViewModel; | ||||
private string filePath; | ||||
private string fileContents; | ||||
/// <summary> | ||||
/// The index in the collection of workspaces of the current workspace. | ||||
/// This property is bound to the SelectedIndex property in the workspaces tab control | ||||
|
@@ -1447,13 +1448,48 @@ public FileDialog GetSaveDialog(WorkspaceModel workspace) | |||
return fileDialog; | ||||
} | ||||
|
||||
/// <summary> | ||||
/// Attempts to open a file using the Json content passed to OpenFromJsonCommand, but wraps | ||||
/// the call with a check to make sure no unsaved changes to the HomeWorkspace are lost. | ||||
/// </summary> | ||||
/// <param name="openFromJsonCommand"> <see cref="DynamoModel.OpenFileFromJsonCommand"/> </param> | ||||
private void OpenFromJsonIfSaved(object openCommand) | ||||
{ | ||||
filePath = string.Empty; | ||||
fileContents = string.Empty; | ||||
|
||||
var command = openCommand as DynamoModel.OpenFileFromJsonCommand; | ||||
if (command == null) | ||||
{ | ||||
return; | ||||
} | ||||
|
||||
if (HomeSpace != null && HomeSpace.HasUnsavedChanges) | ||||
{ | ||||
if (AskUserToSaveWorkspaceOrCancel(HomeSpace)) | ||||
{ | ||||
fileContents = command.FileContents; | ||||
ExecuteCommand(command); | ||||
ShowStartPage = false; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
OpenFromJsonCommand.Execute(new Tuple<string, bool>(command.FileContents, command.ForceManualExecutionMode)); | ||||
ShowStartPage = false; | ||||
} | ||||
} | ||||
|
||||
/// <summary> | ||||
/// Attempts to open a file using the passed open command, but wraps the call | ||||
/// with a check to make sure no unsaved changes to the HomeWorkspace are lost. | ||||
/// </summary> | ||||
/// <param name="openCommand"> <see cref="DynamoModel.OpenFileCommand"/> </param> | ||||
private void OpenIfSaved(object openCommand) | ||||
{ | ||||
fileContents = string.Empty; | ||||
filePath = string.Empty; | ||||
|
||||
var command = openCommand as DynamoModel.OpenFileCommand; | ||||
if (command == null) | ||||
{ | ||||
|
@@ -1464,16 +1500,71 @@ private void OpenIfSaved(object openCommand) | |||
{ | ||||
if (AskUserToSaveWorkspaceOrCancel(HomeSpace)) | ||||
{ | ||||
this.filePath = command.FilePath; | ||||
this.ExecuteCommand(command); | ||||
this.ShowStartPage = false; | ||||
filePath = command.FilePath; | ||||
ExecuteCommand(command); | ||||
ShowStartPage = false; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
this.OpenCommand.Execute(new Tuple<string,bool>(command.FilePath, command.ForceManualExecutionMode)); | ||||
this.ShowStartPage = false; | ||||
OpenCommand.Execute(new Tuple<string,bool>(command.FilePath, command.ForceManualExecutionMode)); | ||||
ShowStartPage = false; | ||||
} | ||||
} | ||||
|
||||
/// <summary> | ||||
/// Open a definition or workspace. | ||||
/// </summary> | ||||
/// <param name="parameters"></param> | ||||
/// For most cases, parameters variable refers to the Json content file to open | ||||
/// However, when this command is used in OpenFileDialog, the variable is | ||||
/// a Tuple<string, bool> instead. The boolean flag is used to override the | ||||
/// RunSetting of the workspace. | ||||
private void OpenFromJson(object parameters) | ||||
{ | ||||
// try catch for exceptions thrown while opening files, say from a future version, | ||||
// that can't be handled reliably | ||||
filePath = string.Empty; | ||||
fileContents = string.Empty; | ||||
bool forceManualMode = false; | ||||
try | ||||
{ | ||||
var packedParams = parameters as Tuple<string, bool>; | ||||
if (packedParams != null) | ||||
{ | ||||
fileContents = packedParams.Item1; | ||||
forceManualMode = packedParams.Item2; | ||||
} | ||||
else | ||||
{ | ||||
fileContents = parameters as string; | ||||
} | ||||
ExecuteCommand(new DynamoModel.OpenFileFromJsonCommand(fileContents, forceManualMode)); | ||||
} | ||||
catch (Exception e) | ||||
{ | ||||
if (!DynamoModel.IsTestMode) | ||||
{ | ||||
string commandString = String.Format(Resources.MessageErrorOpeningFileGeneral); | ||||
string errorMsgString; | ||||
if (e is Newtonsoft.Json.JsonReaderException) | ||||
{ | ||||
errorMsgString = String.Format(Resources.MessageFailedToOpenCorruptedFile, "Json file content"); | ||||
} | ||||
else | ||||
{ | ||||
errorMsgString = String.Format(Resources.MessageUnkownErrorOpeningFile, "Json file content"); | ||||
} | ||||
model.Logger.LogNotification("Dynamo", commandString, errorMsgString, e.ToString()); | ||||
System.Windows.MessageBox.Show(errorMsgString); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we want to use the new themed dialog box where possible - @QilongTang @RobertGlobant20 can you point to an example of this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refer to this PR: https://github.com/DynamoDS/Dynamo/pull/12655/files |
||||
} | ||||
else | ||||
{ | ||||
throw (e); | ||||
} | ||||
return; | ||||
} | ||||
this.ShowStartPage = false; // Hide start page if there's one. | ||||
} | ||||
|
||||
/// <summary> | ||||
|
@@ -1489,6 +1580,7 @@ private void Open(object parameters) | |||
// try catch for exceptions thrown while opening files, say from a future version, | ||||
// that can't be handled reliably | ||||
filePath = string.Empty; | ||||
fileContents = string.Empty; | ||||
bool forceManualMode = false; | ||||
try | ||||
{ | ||||
|
@@ -1541,17 +1633,42 @@ private bool CanOpen(object parameters) | |||
return PathHelper.IsValidPath(filePath); | ||||
} | ||||
|
||||
private bool CanOpenFromJson(object parameters) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about reusing this helper? Dynamo/src/DynamoUtilities/PathHelper.cs Line 136 in ad0dcca
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please reuse the helper, I put a lot of thoughts into it.. Feel free to update as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||
{ | ||||
string fileContent = parameters as string; | ||||
if (string.IsNullOrEmpty(fileContent)) | ||||
{ | ||||
return false; | ||||
} | ||||
|
||||
try | ||||
{ | ||||
var obj = Newtonsoft.Json.Linq.JToken.Parse(fileContent); | ||||
return true; | ||||
} | ||||
catch (Exception e) | ||||
{ | ||||
Dynamo.Logging.LogMessage.Error(e); | ||||
} | ||||
|
||||
return false; | ||||
} | ||||
|
||||
/// <summary> | ||||
/// Read the contents of the file and set the view parameters for that current workspace | ||||
/// </summary> | ||||
private void model_ComputeModelDeserialized() | ||||
{ | ||||
if (filePath == String.Empty) return; | ||||
string fileContents = File.ReadAllText(filePath); | ||||
{ | ||||
try | ||||
{ | ||||
string fileContentsInUse = String.IsNullOrEmpty(filePath) ? fileContents : File.ReadAllText(filePath); | ||||
if (string.IsNullOrEmpty(fileContentsInUse)) | ||||
{ | ||||
return; | ||||
} | ||||
|
||||
// This call will fail in the case of an XML file | ||||
ExtraWorkspaceViewInfo viewInfo = WorkspaceViewModel.ExtraWorkspaceViewInfoFromJson(fileContents); | ||||
ExtraWorkspaceViewInfo viewInfo = WorkspaceViewModel.ExtraWorkspaceViewInfoFromJson(fileContentsInUse); | ||||
|
||||
Model.CurrentWorkspace.UpdateWithExtraWorkspaceViewInfo(viewInfo); | ||||
Model.OnWorkspaceOpening(viewInfo); | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,8 @@ private static void RegisterDebugModes() | |
|
||
internal static void LoadDebugModesStatusFromConfig(string configPath) | ||
{ | ||
if (!File.Exists(configPath)) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
try | ||
{ | ||
XmlDocument xmlDoc; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this check back because Path.GetDirectoryName throws when filePath is null.