Skip to content

Commit 1cf0f2e

Browse files
mlqnlassopicasso
andauthored
feat: Delete all Summary 2.0 components that has a reference to a deleted component (#14126)
Co-authored-by: Lars <[email protected]>
1 parent b59e9cc commit 1cf0f2e

File tree

57 files changed

+1513
-118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1513
-118
lines changed

backend/src/Designer/Controllers/AppDevelopmentController.cs

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Linq;
45
using System.Text.Json.Nodes;
56
using System.Threading;
67
using System.Threading.Tasks;
@@ -119,8 +120,17 @@ public async Task<ActionResult> SaveFormLayout(string org, string app, [FromQuer
119120

120121
if (formLayoutPayload.ComponentIdsChange is not null && !string.IsNullOrEmpty(layoutSetName))
121122
{
122-
foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange)
123+
foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange.Where((componentIdChange) => componentIdChange.OldComponentId != componentIdChange.NewComponentId))
123124
{
125+
if (componentIdChange.NewComponentId == null)
126+
{
127+
await _mediator.Publish(new ComponentDeletedEvent
128+
{
129+
ComponentId = componentIdChange.OldComponentId,
130+
LayoutSetName = layoutSetName,
131+
EditingContext = editingContext
132+
}, cancellationToken);
133+
}
124134
await _mediator.Publish(new ComponentIdChangedEvent
125135
{
126136
OldComponentId = componentIdChange.OldComponentId,
@@ -155,16 +165,26 @@ await _mediator.Publish(new LayoutPageAddedEvent
155165
/// <param name="app">Application identifier which is unique within an organisation.</param>
156166
/// <param name="layoutSetName">The name of the layout set the specific layout belongs to</param>
157167
/// <param name="layoutName">The form layout to be deleted</param>
168+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
158169
/// <returns>A success message if the save was successful</returns>
159170
[HttpDelete]
160171
[Route("form-layout/{layoutName}")]
161-
public ActionResult DeleteFormLayout(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName)
172+
public async Task<ActionResult> DeleteFormLayout(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, CancellationToken cancellationToken)
162173
{
163174
try
164175
{
165176
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
166177
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer);
178+
179+
await _mediator.Publish(new LayoutPageDeletedEvent
180+
{
181+
EditingContext = editingContext,
182+
LayoutSetName = layoutSetName,
183+
LayoutName = layoutName,
184+
}, cancellationToken);
185+
167186
_appDevelopmentService.DeleteFormLayout(editingContext, layoutSetName, layoutName);
187+
168188
return Ok();
169189
}
170190
catch (FileNotFoundException exception)
@@ -398,13 +418,15 @@ public async Task<ActionResult> DeleteLayoutSet(string org, string app, [FromRou
398418
{
399419
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
400420
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer);
401-
LayoutSets layoutSets = await _appDevelopmentService.DeleteLayoutSet(editingContext, layoutSetIdToUpdate, cancellationToken);
402421

403422
await _mediator.Publish(new LayoutSetDeletedEvent
404423
{
405424
EditingContext = editingContext,
406-
LayoutSetId = layoutSetIdToUpdate
425+
LayoutSetName = layoutSetIdToUpdate
407426
}, cancellationToken);
427+
428+
LayoutSets layoutSets = await _appDevelopmentService.DeleteLayoutSet(editingContext, layoutSetIdToUpdate, cancellationToken);
429+
408430
return Ok(layoutSets);
409431
}
410432

backend/src/Designer/Controllers/ResourceAdminController.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ public async Task<ActionResult<List<AvailableService>>> GetAltinn2LinkServices(s
487487
foreach (ServiceResource resource in allResources)
488488
{
489489
if (resource?.HasCompetentAuthority.Orgcode != null
490-
&& resource.ResourceReferences != null && resource.ResourceReferences.Exists(r => r.ReferenceType != null && r.ReferenceType.Equals(ReferenceType.ServiceCode))
490+
&& resource.ResourceReferences != null && resource.ResourceReferences.Exists(r => r.ReferenceType != null && r.ReferenceType.Equals(ResourceReferenceType.ServiceCode))
491491
&& resource.ResourceType == ResourceType.Altinn2Service)
492492
{
493493
AvailableService service = new AvailableService();
@@ -496,8 +496,8 @@ public async Task<ActionResult<List<AvailableService>>> GetAltinn2LinkServices(s
496496
service.ServiceName = resource.Title["nb"];
497497
}
498498

499-
service.ExternalServiceCode = resource.ResourceReferences.First(r => r.ReferenceType.Equals(ReferenceType.ServiceCode)).Reference;
500-
service.ExternalServiceEditionCode = Convert.ToInt32(resource.ResourceReferences.First(r => r.ReferenceType.Equals(ReferenceType.ServiceEditionCode)).Reference);
499+
service.ExternalServiceCode = resource.ResourceReferences.First(r => r.ReferenceType.Equals(ResourceReferenceType.ServiceCode)).Reference;
500+
service.ExternalServiceEditionCode = Convert.ToInt32(resource.ResourceReferences.First(r => r.ReferenceType.Equals(ResourceReferenceType.ServiceEditionCode)).Reference);
501501
service.ServiceOwnerCode = resource.HasCompetentAuthority.Orgcode;
502502
unfiltered.Add(service);
503503
}
@@ -551,7 +551,7 @@ private ValidationProblemDetails ValidateResource(ServiceResource resource)
551551

552552
if (resource.ResourceType == ResourceType.MaskinportenSchema)
553553
{
554-
if (resource.ResourceReferences == null || !resource.ResourceReferences.Any((x) => x.ReferenceType == ReferenceType.MaskinportenScope))
554+
if (resource.ResourceReferences == null || !resource.ResourceReferences.Any((x) => x.ReferenceType == ResourceReferenceType.MaskinportenScope))
555555
{
556556
ModelState.AddModelError($"{resource.Identifier}.resourceReferences", "resourceerror.missingmaskinportenscope");
557557
}
+3-25
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,9 @@
1-
using System.Runtime.Serialization;
2-
31
namespace Altinn.Studio.Designer.Enums
42
{
5-
/// <summary>
6-
/// Enum for reference types of resources in the resource registry
7-
/// </summary>
83
public enum ReferenceType
94
{
10-
[EnumMember(Value = "Default")]
11-
Default = 0,
12-
13-
[EnumMember(Value = "Uri")]
14-
Uri = 1,
15-
16-
[EnumMember(Value = "DelegationSchemeId")]
17-
DelegationSchemeId = 2,
18-
19-
[EnumMember(Value = "MaskinportenScope")]
20-
MaskinportenScope = 3,
21-
22-
[EnumMember(Value = "ServiceCode")]
23-
ServiceCode = 4,
24-
25-
[EnumMember(Value = "ServiceEditionCode")]
26-
ServiceEditionCode = 5,
27-
28-
[EnumMember(Value = "ApplicationId")]
29-
ApplicationId = 6,
5+
LayoutSet,
6+
Layout,
7+
Component
308
}
319
}

backend/src/Designer/Enums/ReferenceSource.cs backend/src/Designer/Enums/ResourceReferenceSource.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Altinn.Studio.Designer.Enums
55
/// <summary>
66
/// Enum for the different reference sources for resources in the resource registry
77
/// </summary>
8-
public enum ReferenceSource
8+
public enum ResourceReferenceSource
99
{
1010
[EnumMember(Value = "Default")]
1111
Default = 0,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Runtime.Serialization;
2+
3+
namespace Altinn.Studio.Designer.Enums
4+
{
5+
/// <summary>
6+
/// Enum for reference types of resources in the resource registry
7+
/// </summary>
8+
public enum ResourceReferenceType
9+
{
10+
[EnumMember(Value = "Default")]
11+
Default = 0,
12+
13+
[EnumMember(Value = "Uri")]
14+
Uri = 1,
15+
16+
[EnumMember(Value = "DelegationSchemeId")]
17+
DelegationSchemeId = 2,
18+
19+
[EnumMember(Value = "MaskinportenScope")]
20+
MaskinportenScope = 3,
21+
22+
[EnumMember(Value = "ServiceCode")]
23+
ServiceCode = 4,
24+
25+
[EnumMember(Value = "ServiceEditionCode")]
26+
ServiceEditionCode = 5,
27+
28+
[EnumMember(Value = "ApplicationId")]
29+
ApplicationId = 6,
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Altinn.Studio.Designer.Enums;
5+
using Altinn.Studio.Designer.Events;
6+
using Altinn.Studio.Designer.Hubs.SyncHub;
7+
using Altinn.Studio.Designer.Models;
8+
using Altinn.Studio.Designer.Services.Interfaces;
9+
using MediatR;
10+
11+
namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted;
12+
13+
public class ComponentDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler<ComponentDeletedEvent>
14+
{
15+
public async Task Handle(ComponentDeletedEvent notification, CancellationToken cancellationToken)
16+
{
17+
await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
18+
notification.EditingContext,
19+
SyncErrorCodes.ComponentDeletedLayoutsSyncError,
20+
"layouts",
21+
async () =>
22+
{
23+
List<Reference> referencesToDelete = [new Reference(ReferenceType.Component, notification.LayoutSetName, notification.ComponentId)];
24+
return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken);
25+
});
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Altinn.Studio.Designer.Enums;
5+
using Altinn.Studio.Designer.Events;
6+
using Altinn.Studio.Designer.Hubs.SyncHub;
7+
using Altinn.Studio.Designer.Models;
8+
using Altinn.Studio.Designer.Services.Interfaces;
9+
using MediatR;
10+
11+
namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted;
12+
13+
public class LayoutPageDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler<LayoutPageDeletedEvent>
14+
{
15+
public async Task Handle(LayoutPageDeletedEvent notification, CancellationToken cancellationToken)
16+
{
17+
await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
18+
notification.EditingContext,
19+
SyncErrorCodes.LayoutPageDeletedLayoutsSyncError,
20+
"layouts",
21+
async () =>
22+
{
23+
List<Reference> referencesToDelete = [new Reference(ReferenceType.Layout, notification.LayoutSetName, notification.LayoutName)];
24+
return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken);
25+
});
26+
}
27+
}

backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs

-73
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Altinn.Studio.Designer.Enums;
5+
using Altinn.Studio.Designer.Events;
6+
using Altinn.Studio.Designer.Hubs.SyncHub;
7+
using Altinn.Studio.Designer.Models;
8+
using Altinn.Studio.Designer.Services.Interfaces;
9+
using MediatR;
10+
11+
namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted;
12+
13+
public class LayoutSetDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler<LayoutSetDeletedEvent>
14+
{
15+
public async Task Handle(LayoutSetDeletedEvent notification, CancellationToken cancellationToken)
16+
{
17+
await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
18+
notification.EditingContext,
19+
SyncErrorCodes.LayoutSetDeletedLayoutsSyncError,
20+
"layouts",
21+
async () =>
22+
{
23+
List<Reference> referencesToDelete = [new Reference(ReferenceType.LayoutSet, notification.LayoutSetName, notification.LayoutSetName)];
24+
return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken);
25+
});
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Altinn.Studio.Designer.Models;
2+
using MediatR;
3+
4+
namespace Altinn.Studio.Designer.Events;
5+
6+
public class ComponentDeletedEvent : INotification
7+
{
8+
public AltinnRepoEditingContext EditingContext { get; set; }
9+
public string LayoutSetName { get; set; }
10+
public string ComponentId { get; set; }
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Altinn.Studio.Designer.Models;
2+
using MediatR;
3+
4+
namespace Altinn.Studio.Designer.Events;
5+
6+
public class LayoutPageDeletedEvent : INotification
7+
{
8+
public AltinnRepoEditingContext EditingContext { get; set; }
9+
public string LayoutSetName { get; set; }
10+
public string LayoutName { get; set; }
11+
}

backend/src/Designer/Events/LayoutSetDeletedEvent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ namespace Altinn.Studio.Designer.Events;
55

66
public class LayoutSetDeletedEvent : INotification
77
{
8-
public string LayoutSetId { get; set; }
98
public AltinnRepoEditingContext EditingContext { get; set; }
9+
public string LayoutSetName { get; set; }
1010
}

backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ public static class SyncErrorCodes
99
public const string ApplicationMetadataDataTypeSyncError = nameof(ApplicationMetadataDataTypeSyncError);
1010
public const string LayoutSetsDataTypeSyncError = nameof(LayoutSetsDataTypeSyncError);
1111
public const string LayoutSetComponentIdSyncError = nameof(LayoutSetComponentIdSyncError);
12-
public const string LayoutSetSubLayoutSyncError = nameof(LayoutSetSubLayoutSyncError);
12+
public const string LayoutSetDeletedLayoutsSyncError = nameof(LayoutSetDeletedLayoutsSyncError);
1313
public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError);
1414
public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError);
1515
public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError);
16+
public const string ComponentDeletedLayoutsSyncError = nameof(ComponentDeletedLayoutsSyncError);
17+
public const string LayoutPageDeletedLayoutsSyncError = nameof(LayoutPageDeletedLayoutsSyncError);
1618
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
using Altinn.Studio.Designer.Enums;
3+
4+
namespace Altinn.Studio.Designer.Models
5+
{
6+
public record Reference(ReferenceType Type, string LayoutSetName, string Id, string NewId = null);
7+
}

0 commit comments

Comments
 (0)