Skip to content

Commit 7a7e88a

Browse files
committed
Any change to proces data model file and initialization script are saved as change are done
1. When editing data model files or initialization script files for projects, we are currently saving changes only locally. The changes are actually pushed to service only when we do a File -> Save. We will immediately push the changes if the user clicks save on the code/script editor after editing data model or initialization script files. If user chooes cancel, changes will be discarded. 2. When deleting a component which can have scripts associated with them, we show a dialog that let users to decide if they would like to delete the scripts as well. We are only deleting these scripts locally only. These scripts will be deleted in the backend as well now if user decides to delete them. 3. When creating a new project, save the process, datamodel and initialization script file immediately after loading the project for the first time.
1 parent 6b9b05c commit 7a7e88a

File tree

25 files changed

+408
-138
lines changed

25 files changed

+408
-138
lines changed

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/AutomationEditorViewModel.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,47 @@ public override async Task EditDataModelAsync()
100100
{
101101
logger.Information($"Opening code editor for editing data model for project : {this.CurrentProject.Name}");
102102
var editorFactory = this.EntityManager.GetServiceOfType<ICodeEditorFactory>();
103+
var projectFileSystem = this.projectManager.GetProjectFileSystem();
103104
using (var editor = editorFactory.CreateMultiCodeEditorScreen())
104105
{
105-
foreach (var file in Directory.GetFiles(this.projectManager.GetProjectFileSystem().DataModelDirectory, "*.cs"))
106+
foreach (var file in Directory.GetFiles(projectFileSystem.DataModelDirectory, "*.cs"))
106107
{
107108
await editor.AddDocumentAsync(Path.GetFileName(file), this.CurrentProject.Name, File.ReadAllText(file), false);
108109
}
109110

110111
await editor.AddDocumentAsync($"{Constants.AutomationProcessDataModelName}.cs", this.CurrentProject.Name, string.Empty, false);
111-
await editor.OpenDocumentAsync($"{Constants.AutomationProcessDataModelName}.cs", this.CurrentProject.Name);
112-
112+
await editor.OpenDocumentAsync($"{Constants.AutomationProcessDataModelName}.cs", this.CurrentProject.Name);
113+
113114
bool? hasChanges = await this.windowManager.ShowDialogAsync(editor);
115+
var editorDocumentStates = editor.GetCurrentEditorState();
116+
114117
if (hasChanges.HasValue && !hasChanges.Value)
115118
{
119+
logger.Information("Discarding changes for data model files");
120+
foreach (var document in editorDocumentStates)
121+
{
122+
if(document.IsNewDocument)
123+
{
124+
File.Delete(Path.Combine(projectFileSystem.DataModelDirectory, document.TargetDocument));
125+
logger.Information("Delete file {@0} from data model files", document);
126+
}
127+
}
116128
return;
117129
}
118-
}
119-
logger.Information($"Editing data model completed for project : {this.CurrentProject.Name}");
120-
130+
131+
foreach (var document in editorDocumentStates)
132+
{
133+
if ((document.IsNewDocument || document.IsModified) && !document.IsDeleted)
134+
{
135+
await this.projectManager.AddOrUpdateDataFileAsync(Path.Combine(projectFileSystem.DataModelDirectory, document.TargetDocument));
136+
}
137+
if(document.IsDeleted && !document.IsNewDocument)
138+
{
139+
await this.projectManager.DeleteDataFileAsync(Path.Combine(projectFileSystem.DataModelDirectory, document.TargetDocument));
140+
}
141+
logger.Information("Updated state of data model file {@0}", document);
142+
}
143+
}
121144
await this.Reload();
122145
}
123146
catch (Exception ex)
@@ -155,6 +178,8 @@ public async Task EditScriptAsync()
155178
var scriptEngine = entityManager.GetScriptEngine();
156179
scriptEngine.ClearState();
157180
await scriptEngine.ExecuteFileAsync(scriptFile);
181+
await this.projectManager.AddOrUpdateDataFileAsync(scriptFile);
182+
logger.Information("Updated script file : {0}", scriptFile);
158183
}
159184
scriptEditorFactory.RemoveProject(this.CurrentProject.Name);
160185
}

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/AutomationProjectManager.cs

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -124,33 +124,25 @@ private void Initialize()
124124
if (!File.Exists(this.projectFileSystem.ProcessFile))
125125
{
126126
this.RootEntity = new ProcessRootEntity();
127+
this.RootEntity.AddComponent(new ApplicationPoolEntity());
128+
this.RootEntity.AddComponent(new OneTimeSetUpEntity() { Name = "Environment Setup" });
129+
this.RootEntity.AddComponent(new OneTimeTearDownEntity() { Name = "Environment Teardown" });
130+
this.serializer.Serialize<Entity>(this.projectFileSystem.ProcessFile, this.RootEntity);
127131
}
128132
else
129133
{
130134
this.RootEntity = DeserializeProject();
131135
}
132-
133-
AddDefaultEntities();
136+
RestoreParentChildRelation(this.RootEntity);
137+
134138
logger.Information($"Project file for {this.GetProjectName()} has been loaded ");
135139
}
136140

137141
private Entity DeserializeProject()
138142
{
139143
var entity = this.Load<Entity>(this.projectFileSystem.ProcessFile);
140144
return entity;
141-
}
142-
143-
144-
private void AddDefaultEntities()
145-
{
146-
if (this.RootEntity.Components.Count() == 0)
147-
{
148-
this.RootEntity.AddComponent(new ApplicationPoolEntity());
149-
this.RootEntity.AddComponent(new OneTimeSetUpEntity() { Name = "Environment Setup" });
150-
this.RootEntity.AddComponent(new OneTimeTearDownEntity() { Name = "Environment Teardown" });
151-
}
152-
RestoreParentChildRelation(this.RootEntity);
153-
}
145+
}
154146

155147
#endregion Load Project
156148

@@ -194,6 +186,30 @@ public override async Task Reload()
194186

195187
#region overridden methods
196188

189+
///<inheritdoc/>
190+
public override async Task AddOrUpdateDataFileAsync(string targetFile)
191+
{
192+
await this.projectDataManager.AddOrUpdateDataFileAsync(this.activeProject, this.loadedVersion as ProjectVersion, targetFile, this.activeProject.ProjectId);
193+
}
194+
195+
///<inheritdoc/>
196+
public override async Task DeleteDataFileAsync(string fileToDelete)
197+
{
198+
await this.projectDataManager.DeleteDataFileAsync(this.activeProject, this.loadedVersion as ProjectVersion, fileToDelete);
199+
}
200+
201+
///<inheritdoc/>
202+
protected override string GetProjectName()
203+
{
204+
return this.activeProject.Name;
205+
}
206+
207+
///<inheritdoc/>
208+
protected override string GetProjectNamespace()
209+
{
210+
return this.activeProject.Namespace;
211+
}
212+
197213
/// <summary>
198214
/// Save automation project and process
199215
/// </summary>
@@ -221,16 +237,6 @@ public override async Task Save()
221237
await this.projectDataManager.SaveProjectDataAsync(this.activeProject, this.loadedVersion as ProjectVersion);
222238
}
223239

224-
protected override string GetProjectName()
225-
{
226-
return this.activeProject.Name;
227-
}
228-
229-
protected override string GetProjectNamespace()
230-
{
231-
return this.activeProject.Namespace;
232-
}
233-
234240
#endregion overridden methods
235241
}
236242
}

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/EditorViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public async Task DeleteComponent(ComponentViewModel componentViewModel)
9494
scripts = this.scriptExtractor.ExtractScripts(componentViewModel.Model).ToList();
9595
}
9696

97-
var deleteScriptsViewModel = new DeleteComponentViewModel(componentViewModel, scripts ?? Enumerable.Empty<ScriptStatus>());
97+
var deleteScriptsViewModel = new DeleteComponentViewModel(componentViewModel, scripts ?? Enumerable.Empty<ScriptStatus>(), projectManager);
9898
var result = await this.windowManager.ShowDialogAsync(deleteScriptsViewModel);
9999
if (!result.GetValueOrDefault())
100100
{

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/PrefabEditorViewModel.cs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Pixel.Automation.Designer.ViewModels.AutomationBuilder;
77
using Pixel.Automation.Editor.Core.Interfaces;
88
using Pixel.Scripting.Editor.Core.Contracts;
9+
using Serilog;
910
using System.Diagnostics;
1011
using System.IO;
1112
using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget;
@@ -14,6 +15,7 @@ namespace Pixel.Automation.Designer.ViewModels
1415
{
1516
public class PrefabEditorViewModel : EditorViewModel , IPrefabEditor
1617
{
18+
private readonly ILogger logger = Log.ForContext<PrefabEditorViewModel>();
1719
private readonly IServiceResolver serviceResolver;
1820
private readonly IPrefabProjectManager projectManager;
1921

@@ -60,20 +62,47 @@ public async Task DoLoad(PrefabProject prefabProject, VersionInfo versionToLoad
6062
public override async Task EditDataModelAsync()
6163
{
6264
var editorFactory = this.EntityManager.GetServiceOfType<ICodeEditorFactory>();
65+
var prefabFileSystem = this.projectManager.GetProjectFileSystem();
6366
using (var editor = editorFactory.CreateMultiCodeEditorScreen())
6467
{
6568
foreach (var file in Directory.GetFiles(this.projectManager.GetProjectFileSystem().DataModelDirectory, "*.cs"))
6669
{
6770
await editor.AddDocumentAsync(Path.GetFileName(file), this.PrefabProject.PrefabName, File.ReadAllText(file), false);
6871
}
6972
await editor.AddDocumentAsync($"{Constants.PrefabDataModelName}.cs", this.PrefabProject.PrefabName, string.Empty, false);
70-
await editor.OpenDocumentAsync($"{Constants.PrefabDataModelName}.cs", this.PrefabProject.PrefabName);
71-
72-
await this.windowManager.ShowDialogAsync(editor);
73+
await editor.OpenDocumentAsync($"{Constants.PrefabDataModelName}.cs", this.PrefabProject.PrefabName);
7374

74-
await this.Reload();
75-
}
76-
75+
bool? hasChanges = await this.windowManager.ShowDialogAsync(editor);
76+
var editorDocumentStates = editor.GetCurrentEditorState();
77+
78+
if (hasChanges.HasValue && !hasChanges.Value)
79+
{
80+
logger.Information("Discarding changes for data model files");
81+
foreach (var document in editorDocumentStates)
82+
{
83+
if (document.IsNewDocument)
84+
{
85+
File.Delete(Path.Combine(prefabFileSystem.DataModelDirectory, document.TargetDocument));
86+
logger.Information("Delete file {@0} from data model files", document);
87+
}
88+
}
89+
return;
90+
}
91+
92+
foreach (var document in editorDocumentStates)
93+
{
94+
if ((document.IsNewDocument || document.IsModified) && !document.IsDeleted)
95+
{
96+
await this.projectManager.AddOrUpdateDataFileAsync(Path.Combine(prefabFileSystem.DataModelDirectory, document.TargetDocument));
97+
}
98+
if (document.IsDeleted && !document.IsNewDocument)
99+
{
100+
await this.projectManager.DeleteDataFileAsync(Path.Combine(prefabFileSystem.DataModelDirectory, document.TargetDocument));
101+
}
102+
logger.Information("Updated state of data model file {@0}", document);
103+
}
104+
}
105+
await this.Reload();
77106
}
78107

79108
protected override async Task Reload()

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/PrefabProjectManager.cs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,30 @@ public override async Task Reload()
211211

212212
#region overridden methods
213213

214+
///<inheritdoc/>
215+
public override async Task AddOrUpdateDataFileAsync(string targetFile)
216+
{
217+
await this.prefabDataManager.AddOrUpdateDataFileAsync(this.prefabProject, this.loadedVersion, targetFile, this.prefabProject.PrefabId);
218+
}
219+
220+
///<inheritdoc/>
221+
public override async Task DeleteDataFileAsync(string fileToDelete)
222+
{
223+
await this.prefabDataManager.DeleteDataFileAsync(this.prefabProject, this.loadedVersion, fileToDelete);
224+
}
225+
226+
/// <inheritdoc/>
227+
protected override string GetProjectName()
228+
{
229+
return this.prefabProject.PrefabName;
230+
}
231+
232+
/// <inheritdoc/>
233+
protected override string GetProjectNamespace()
234+
{
235+
return this.prefabProject.Namespace;
236+
}
237+
214238
/// <summary>
215239
/// Save prefab data
216240
/// </summary>
@@ -234,18 +258,7 @@ public override async Task Save()
234258
}
235259
}
236260

237-
/// <inheritdoc/>
238-
protected override string GetProjectName()
239-
{
240-
return this.prefabProject.PrefabName;
241-
}
242-
243-
/// <inheritdoc/>
244-
protected override string GetProjectNamespace()
245-
{
246-
return this.prefabProject.Namespace;
247-
}
248-
261+
249262
#endregion overridden methods
250263
}
251264
}

src/Pixel.Automation.Designer.ViewModels/AutomationBuilder/ProjectManager.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,26 @@ public ProjectManager(ISerializer serializer, IEntityManager entityManager, IFil
6868
protected abstract string GetProjectNamespace();
6969

7070
///<inheritdoc/>
71-
public abstract Task Save();
71+
public abstract Task AddOrUpdateDataFileAsync(string targetFile);
7272

7373
///<inheritdoc/>
74-
public abstract Task Reload();
74+
public abstract Task DeleteDataFileAsync(string fileToDelete);
7575

76-
#endregion abstract methods
76+
///<inheritdoc/>
77+
public abstract Task Save();
7778

7879
///<inheritdoc/>
79-
public IProjectManager WithEntityManager(EntityManager entityManager)
80-
{
81-
this.entityManager = entityManager;
82-
this.entityManager.SetCurrentFileSystem(this.fileSystem);
83-
return this;
84-
}
80+
public abstract Task Reload();
8581

82+
#endregion abstract methods
83+
8684
///<inheritdoc/>
8785
public IFileSystem GetProjectFileSystem()
8886
{
8987
return this.fileSystem;
9088
}
9189

90+
///<inheritdoc/>
9291
public IReferenceManager GetReferenceManager()
9392
{
9493
return this.referenceManager;

src/Pixel.Automation.Designer.ViewModels/Screen/DeleteComponentViewModel.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Caliburn.Micro;
22
using Dawn;
3+
using Pixel.Automation.Editor.Core.Interfaces;
34
using Pixel.Automation.Editor.Core.ViewModels;
45
using Serilog;
56
using System.IO;
@@ -14,7 +15,8 @@ namespace Pixel.Automation.Designer.ViewModels
1415
public class DeleteComponentViewModel : Screen
1516
{
1617
private readonly ILogger logger = Log.ForContext<DeleteComponentViewModel>();
17-
18+
private readonly IProjectManager projectManager;
19+
1820
/// <summary>
1921
/// Component being deleted
2022
/// </summary>
@@ -25,6 +27,9 @@ public class DeleteComponentViewModel : Screen
2527
/// </summary>
2628
public BindableCollection<SelectableItem<string>> Scripts { get; private set; } = new ();
2729

30+
/// <summary>
31+
/// Indicates if there are any script files associated with the component to delete or it's descendants
32+
/// </summary>
2833
public bool HasScripts
2934
{
3035
get => this.Scripts.Any();
@@ -35,12 +40,13 @@ public bool HasScripts
3540
/// </summary>
3641
/// <param name="componentViewModel"></param>
3742
/// <param name="scripts"></param>
38-
public DeleteComponentViewModel(ComponentViewModel componentViewModel, IEnumerable<ScriptStatus> scripts)
43+
public DeleteComponentViewModel(ComponentViewModel componentViewModel, IEnumerable<ScriptStatus> scripts, IProjectManager projectManager)
3944
{
4045
this.DisplayName = "Delete Component";
41-
this.componentViewModel = Guard.Argument(componentViewModel).NotNull();
46+
this.componentViewModel = Guard.Argument(componentViewModel, nameof(componentViewModel)).NotNull();
4247
Guard.Argument(scripts).NotNull();
43-
this.Scripts.AddRange(scripts.Select(s => new SelectableItem<string>(s.ScriptName, true)));
48+
this.Scripts.AddRange(scripts.Select(s => new SelectableItem<string>(s.ScriptName, true)));
49+
this.projectManager = Guard.Argument(projectManager, nameof(projectManager)).NotNull().Value;
4450
}
4551

4652
/// <summary>
@@ -56,8 +62,9 @@ public async Task Delete()
5662
{
5763
if(script.IsSelected)
5864
{
59-
File.Delete(Path.Combine(fileSystem.WorkingDirectory, script.Item));
60-
logger.Information($"Deleted script file {script.Item}");
65+
await this.projectManager.DeleteDataFileAsync(Path.Combine(fileSystem.WorkingDirectory, script.Item));
66+
logger.Information("Script File '{0}' was deleted", script.Item);
67+
6168
}
6269
}
6370
catch (Exception ex)

0 commit comments

Comments
 (0)