Skip to content

Commit 1cd2d65

Browse files
authored
Merge pull request #194 from Nfactor26/allow-prefabs-to-be-deleted
Allow prefabs to be deleted
2 parents 73cd72c + 2fb744b commit 1cd2d65

File tree

17 files changed

+262
-27
lines changed

17 files changed

+262
-27
lines changed

src/Pixel.Automation.AppExplorer.ViewModels/Prefab/PrefabExplorerViewModel.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Pixel.Persistence.Services.Client.Interfaces;
1212
using Serilog;
1313
using System.ComponentModel;
14+
using System.Windows;
1415
using System.Windows.Data;
1516

1617
namespace Pixel.Automation.AppExplorer.ViewModels.Prefab
@@ -113,6 +114,10 @@ private List<PrefabProjectViewModel> LoadPrefabs(ApplicationDescriptionViewModel
113114
var prefabs = this.prefabDataManager.GetPrefabsForScreen(applicationDescriptionViewModel.Model, screenName).ToList();
114115
foreach (var prefab in prefabs)
115116
{
117+
if(prefab.IsDeleted)
118+
{
119+
continue;
120+
}
116121
var prefabProjectViewModel = new PrefabProjectViewModel(prefab);
117122
applicationDescriptionViewModel.AddPrefab(prefabProjectViewModel, screenName);
118123
prefabsList.Add(prefabProjectViewModel);
@@ -231,6 +236,26 @@ public async Task ManagePrefab(PrefabProjectViewModel targetPrefab)
231236
}
232237
}
233238

239+
/// <summary>
240+
/// Delete the prefab
241+
/// </summary>
242+
/// <param name="prefabToDelete"></param>
243+
public async Task DeletePrefabAsync(PrefabProjectViewModel prefabToDelete)
244+
{
245+
try
246+
{
247+
Guard.Argument(prefabToDelete, nameof(prefabToDelete)).NotNull();
248+
await this.prefabDataManager.DeletePrefbAsync(prefabToDelete.PrefabProject);
249+
this.Prefabs.Remove(prefabToDelete);
250+
}
251+
catch (Exception ex)
252+
{
253+
logger.Error(ex, "There was an error while trying to delete prefab : {0}", prefabToDelete.PrefabName);
254+
MessageBox.Show($"Error while deleting prefab : {prefabToDelete.PrefabName}", "Delete Error", MessageBoxButton.OK, MessageBoxImage.Error);
255+
}
256+
}
257+
258+
234259
/// <summary>
235260
/// Broadcast a FilterTestMessage which is processed by Test explorer view to filter and show only those test cases
236261
/// which uses this prefab

src/Pixel.Automation.AppExplorer.ViewModels/Prefab/PrefabVersionManagerViewModel.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Pixel.Persistence.Services.Client.Interfaces;
99
using Pixel.Scripting.Editor.Core.Contracts;
1010
using Serilog;
11+
using System.Windows;
1112

1213
namespace Pixel.Automation.AppExplorer.ViewModels.Prefab
1314
{
@@ -61,7 +62,8 @@ public PrefabVersionManagerViewModel(PrefabProject prefabProject, IWorkspaceMana
6162
public async Task PublishAsync(PrefabVersionViewModel prefabVersionViewModel)
6263
{
6364
try
64-
{
65+
{
66+
Guard.Argument(prefabVersionViewModel, nameof(prefabVersionViewModel)).NotNull();
6567
if (!prefabVersionViewModel.IsPublished)
6668
{
6769
bool isLatestActieVersion = prefabProject.LatestActiveVersion.Version.Equals(prefabVersionViewModel.Version);
@@ -75,7 +77,8 @@ public async Task PublishAsync(PrefabVersionViewModel prefabVersionViewModel)
7577
}
7678
catch (Exception ex)
7779
{
78-
logger.Error(ex, ex.Message);
80+
logger.Error(ex, "There was an error while trying to publish verion : {0} of prefab : {1}", prefabVersionViewModel.Version, prefabVersionViewModel.PrefabName);
81+
MessageBox.Show($"Error while publishing version {prefabVersionViewModel.Version} of prefab {prefabVersionViewModel.PrefabName}", "Publish Error", MessageBoxButton.OK, MessageBoxImage.Error);
7982
}
8083
}
8184

@@ -87,6 +90,7 @@ public async Task CloneAsync(PrefabVersionViewModel prefabVersionViewModel)
8790
{
8891
try
8992
{
93+
Guard.Argument(prefabVersionViewModel, nameof(prefabVersionViewModel)).NotNull();
9094
if (prefabVersionViewModel.IsPublished)
9195
{
9296
PrefabVersion newVersion = await prefabVersionViewModel.CloneAsync(this.prefabDataManager);
@@ -98,7 +102,8 @@ public async Task CloneAsync(PrefabVersionViewModel prefabVersionViewModel)
98102
}
99103
catch (Exception ex)
100104
{
101-
logger.Error(ex, ex.Message);
105+
logger.Error(ex, "There was an error while trying to create a new verion of prefab : {0} from version : {1}", prefabVersionViewModel.PrefabName, prefabVersionViewModel.Version);
106+
MessageBox.Show($"Error while cloning version {prefabVersionViewModel.Version} of prefab {prefabVersionViewModel.PrefabName}", "Clone Error", MessageBoxButton.OK, MessageBoxImage.Error);
102107
}
103108
}
104109

src/Pixel.Automation.AppExplorer.ViewModels/Prefab/PrefabVersionViewModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ public class PrefabVersionViewModel : PropertyChangedBase
2020
private readonly IPrefabFileSystem fileSystem;
2121
private readonly Lazy<IReferenceManager> referenceManager;
2222

23+
public string PrefabName
24+
{
25+
get => prefabProject.PrefabName;
26+
}
27+
2328
public Version Version
2429
{
2530
get => prefabVersion.Version;

src/Pixel.Automation.AppExplorer.ViewModels/PrefabDropHandler/PrefabVersionSelectorViewModel.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
using Pixel.Automation.Editor.Core.ViewModels;
88
using Pixel.Automation.Reference.Manager;
99
using Pixel.Automation.Reference.Manager.Contracts;
10+
using Pixel.Persistence.Services.Client.Interfaces;
1011
using Serilog;
1112
using System.IO;
13+
using System.Windows;
1214

1315
namespace Pixel.Automation.AppExplorer.ViewModels.PrefabDropHandler
1416
{
@@ -86,13 +88,13 @@ public string OutputMappingScriptFile
8688
/// <param name="prefabProjectViewModel">Prefab which needs to be added to automation process</param>
8789
/// <param name="dropTarget">EntityComponentViewModel wrapping an Entity to which Prefab needs to be added</param>
8890
public PrefabVersionSelectorViewModel(IProjectFileSystem projectFileSystem, IPrefabFileSystem prefabFileSystem,
89-
IReferenceManager projectReferenceManager, PrefabEntity prefabEntity,
91+
IReferenceManager projectReferenceManager, PrefabEntity prefabEntity,
9092
PrefabProjectViewModel prefabProjectViewModel, EntityComponentViewModel dropTarget)
9193
{
9294
this.DisplayName = "(1/3) Select prefab version and mapping scripts";
9395
this.projectFileSystem = projectFileSystem;
9496
this.prefabFileSystem = prefabFileSystem;
95-
this.projectReferenceManager = projectReferenceManager;
97+
this.projectReferenceManager = projectReferenceManager;
9698
this.prefabEntity = prefabEntity;
9799
this.prefabProject = prefabProjectViewModel.PrefabProject;
98100
this.dropTarget = dropTarget;
@@ -142,16 +144,24 @@ public void PickOutputMappingScriptFile()
142144
/// <inheritdoc/>
143145
public override async Task<bool> TryProcessStage()
144146
{
145-
//TODO : Can we make this asyc ?
146-
if(this.SelectedVersion != null && !dropTarget.ComponentCollection.Any(a => a.Model.Equals(prefabEntity)))
147+
try
147148
{
148-
await UpdatePrefabReferencesAsync();
149-
await UpdateControlReferencesAsync();
150-
dropTarget.AddComponent(prefabEntity);
151-
this.CanChangeVersion = false;
152-
logger.Information("Added version {0} of {1} to {2}.", this.SelectedVersion, this.prefabProject, this.dropTarget);
153-
}
154-
return true;
149+
if (this.SelectedVersion != null && !dropTarget.ComponentCollection.Any(a => a.Model.Equals(prefabEntity)))
150+
{
151+
await UpdatePrefabReferencesAsync();
152+
await UpdateControlReferencesAsync();
153+
dropTarget.AddComponent(prefabEntity);
154+
this.CanChangeVersion = false;
155+
logger.Information("Added version {0} of {1} to {2}.", this.SelectedVersion, this.prefabProject, this.dropTarget);
156+
}
157+
return true;
158+
}
159+
catch (Exception ex)
160+
{
161+
logger.Error(ex, "There was an error while trying to process stage for the prefab version selector screen");
162+
MessageBox.Show("Error while trying to add prefab", "Add Prefab Error", MessageBoxButton.OK, MessageBoxImage.Error);
163+
return false;
164+
}
155165
}
156166

157167
/// <summary>

src/Pixel.Automation.AppExplorer.Views/Prefab/PrefabExplorerView.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
cal:Action.TargetWithoutContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=2}}" cal:Message.Attach="[Event Click] = [Action ManagePrefab($dataContext)]"></MenuItem>
9494
<MenuItem x:Name="ShowUsage" Header="Show Usage" cal:Action.TargetWithoutContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=2}}" cal:Message.Attach="[Event Click] = [Action ShowUsage($dataContext)]"></MenuItem>
9595
<MenuItem x:Name="MoveToScreen" Header="Move To Screen" cal:Action.TargetWithoutContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=2}}" cal:Message.Attach="[Event Click] = [Action MoveToScreen($dataContext)]"></MenuItem>
96+
<MenuItem x:Name="Delete" Header="Delete" cal:Action.TargetWithoutContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=2}}" cal:Message.Attach="[Event Click] = [Action DeletePrefabAsync($dataContext)]" ></MenuItem>
9697
</StackPanel>
9798
</ControlTemplate>
9899
</ContextMenu.Template>

src/Pixel.Automation.Core/Models/PrefabProject.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ public class PrefabProject : ICloneable
4949
[DataMember(Order = 70)]
5050
public string GroupName { get; set; } = "Default";
5151

52+
/// <summary>
53+
/// Indicates if Prefab project is marked deleted.
54+
/// </summary>
55+
[DataMember(Order = 1000)]
56+
public bool IsDeleted { get; set; }
57+
5258
/// <summary>
5359
/// Get all the versions that are active.
5460
/// </summary>

src/Pixel.Persistence.Respository/Interfaces/IControlRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public interface IControlRepository
5252
Task<bool> IsControlDeleted(string applicationId, string controlId);
5353

5454
/// <summary>
55-
/// Set IsDeleted flag on all versionf of control to true.
55+
/// Set IsDeleted flag on all versions of control to true.
5656
/// </summary>
5757
/// <param name="applicationId"></param>
5858
/// <param name="controlId"></param>

src/Pixel.Persistence.Respository/Interfaces/IPrefabsRepository.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,19 @@ public interface IPrefabsRepository
5959
/// <param name="cancellationToken"></param>
6060
/// <returns></returns>
6161
Task UpdatePrefabVersionAsync(string prefabId, PrefabVersion version, CancellationToken cancellationToken);
62+
63+
/// <summary>
64+
/// Check if a Prefab is marked deleted
65+
/// </summary>
66+
/// <param name="prefabId"></param>
67+
/// <returns></returns>
68+
Task<bool> IsPrefabDeleted(string prefabId);
69+
70+
/// <summary>
71+
/// Mark prefab as deleted.
72+
/// </summary>
73+
/// <param name="prefabId"></param>
74+
/// <returns></returns>
75+
Task DeletePrefabAsync(string prefabId);
6276
}
6377
}

src/Pixel.Persistence.Respository/Interfaces/IReferencesRepository.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,23 @@ public interface IReferencesRepository
5959
/// <returns></returns>
6060
Task UpdateControlReference(string projectId, string projectVersion, ControlReference controlReference);
6161

62+
63+
/// <summary>
64+
/// Check if any version of prefab is in use by any version of any project
65+
/// </summary>
66+
/// <param name="prefabId"></param>
67+
/// <returns></returns>
68+
Task<bool> IsPrefabInUse(string prefabId);
69+
70+
/// <summary>
71+
/// Check if any of the projets has a reference to any version of this prefab
72+
/// </summary>
73+
/// <param name="projectId"></param>
74+
/// <param name="projectVersion"></param>
75+
/// <param name="controlReference"></param>
76+
/// <returns></returns>
77+
//Task<bool> HasPrefabReference(string projectId, string projectVersion, PrefabReference prefabReference);
78+
6279
/// <summary>
6380
/// Add or update PrefabReferences for a given version of project
6481
/// </summary>

src/Pixel.Persistence.Respository/PrefabsRepository.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Pixel.Persistence.Respository
1717
public class PrefabsRepository : IPrefabsRepository
1818
{
1919
private readonly ILogger logger;
20-
private readonly IMongoCollection<PrefabProject> prefabsCollection;
20+
private readonly IMongoCollection<PrefabProject> prefabsCollection;
2121
private readonly IPrefabFilesRepository prefabFilesRepossitory;
2222
private readonly IReferencesRepository referencesRepository;
2323
private static readonly InsertOneOptions InsertOneOptions = new InsertOneOptions();
@@ -105,7 +105,9 @@ public async Task AddPrefabVersionAsync(string prefabId, PrefabVersion newVersio
105105
}
106106

107107
filter = Builders<PrefabProject>.Filter.Eq(x => x.PrefabId, prefabId);
108-
var push = Builders<PrefabProject>.Update.Push(t => t.AvailableVersions, newVersion);
108+
var push = Builders<PrefabProject>.Update.Push(t => t.AvailableVersions, newVersion)
109+
.Set(t => t.LastUpdated, DateTime.UtcNow)
110+
.Inc(t => t.Revision, 1);
109111
await this.prefabsCollection.UpdateOneAsync(filter, push);
110112
}
111113

@@ -125,12 +127,39 @@ public async Task UpdatePrefabVersionAsync(string prefabId, PrefabVersion prefab
125127
{
126128
prefabVersion.PublishedOn = DateTime.UtcNow;
127129
}
128-
var update = Builders<PrefabProject>.Update.Set(x => x.AvailableVersions[-1], prefabVersion);
130+
var update = Builders<PrefabProject>.Update.Set(x => x.AvailableVersions[-1], prefabVersion)
131+
.Set(t => t.LastUpdated, DateTime.UtcNow)
132+
.Inc(t => t.Revision, 1); ;
129133
await this.prefabsCollection.UpdateOneAsync(filter, update);
130134
logger.LogInformation("Project version {0} was updated for project : {1}", prefabVersion, prefabId);
131135
return;
132136
}
133137
throw new InvalidOperationException($"Version {prefabVersion} doesn't exist on prefab {prefabId}");
134138
}
139+
140+
///<inheritdoc/>
141+
public async Task<bool> IsPrefabDeleted(string prefabId)
142+
{
143+
Guard.Argument(prefabId, nameof(prefabId)).NotNull().NotEmpty();
144+
var filter = Builders<PrefabProject>.Filter.Eq(x => x.PrefabId, prefabId) &
145+
Builders<PrefabProject>.Filter.Eq(x => x.IsDeleted, true);
146+
long count = await this.prefabsCollection.CountDocumentsAsync(filter, new CountOptions() { Limit = 1 });
147+
return count > 0;
148+
}
149+
150+
/// <inheritdoc/>
151+
public async Task DeletePrefabAsync(string prefabId)
152+
{
153+
Guard.Argument(prefabId, nameof(prefabId)).NotNull();
154+
if(await this.referencesRepository.IsPrefabInUse(prefabId))
155+
{
156+
throw new InvalidOperationException("Prefab is in use across one or more projects");
157+
}
158+
var updateFilter = Builders<PrefabProject>.Filter.Eq(x => x.PrefabId, prefabId);
159+
var updateDefinition = Builders<PrefabProject>.Update.Set(x => x.IsDeleted, true)
160+
.Set(x => x.LastUpdated, DateTime.UtcNow)
161+
.Inc(t => t.Revision, 1);
162+
await this.prefabsCollection.FindOneAndUpdateAsync<PrefabProject>(updateFilter, updateDefinition);
163+
}
135164
}
136165
}

0 commit comments

Comments
 (0)