Skip to content
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

feat: Delete all Summary 2.0 components that has a reference to a deleted component #14126

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f3c047d
Delete all Summary 2.0 components that has a reference to deleted com…
mlqn Nov 21, 2024
c1e2922
dotnet format
mlqn Nov 27, 2024
dd249f7
Fix SaveFormLayout
mlqn Nov 27, 2024
ab6681a
Merge remote-tracking branch 'origin/main' into 13525-automatically-d…
mlqn Nov 28, 2024
1920a7b
Add backend tests
mlqn Nov 29, 2024
8cbebb7
Cleanup
mlqn Nov 29, 2024
7f950cb
Refactoring
mlqn Dec 4, 2024
4279b30
Cleanup
mlqn Dec 5, 2024
f058f90
Fix tests
mlqn Dec 6, 2024
4e204a4
Fix tests
mlqn Dec 6, 2024
bda8b14
Fix SaveFormLayout
mlqn Dec 6, 2024
c85740d
Cleanup overrides
mlqn Dec 15, 2024
160d666
Merge remote-tracking branch 'origin/main' into 13525-automatically-d…
mlqn Dec 16, 2024
dcaeb94
Recursive deletion
mlqn Dec 16, 2024
53663af
Fix warnings
mlqn Dec 18, 2024
1739b58
Clean up code
mlqn Dec 19, 2024
f837897
Update Summary2 and Subform when updating component id
mlqn Dec 20, 2024
55c8500
Cleanup code
mlqn Jan 6, 2025
6f54dd2
Merge remote-tracking branch 'origin/main' into 13525-automatically-d…
mlqn Jan 6, 2025
c5a6487
Fix code
mlqn Jan 6, 2025
73e2f93
Cleanup
mlqn Jan 6, 2025
fd717a6
Add tests
mlqn Jan 7, 2025
3d2a84f
Cleanup
mlqn Jan 7, 2025
f91bdbd
Remove update changes
mlqn Jan 7, 2025
6244138
Add frontend warnings
mlqn Jan 7, 2025
7bea3bd
Fixes after CR
mlqn Jan 16, 2025
55806b2
Merge branch 'main' into 13525-automatically-delete-all-summary-20-co…
mlqn Jan 16, 2025
d360473
Merge branch 'main' into 13525-automatically-delete-all-summary-20-co…
mlqn Jan 16, 2025
9c6dbb9
Fix name conflicts
mlqn Jan 16, 2025
7ca7686
Fix coderabbit warnings
mlqn Jan 16, 2025
9ada558
Merge branch 'main' into 13525-automatically-delete-all-summary-20-co…
lassopicasso Jan 17, 2025
0db4933
Fix tests
mlqn Jan 17, 2025
e398474
Merge branch 'main' into 13525-automatically-delete-all-summary-20-co…
lassopicasso Jan 20, 2025
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
30 changes: 26 additions & 4 deletions backend/src/Designer/Controllers/AppDevelopmentController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -119,8 +120,17 @@ public async Task<ActionResult> SaveFormLayout(string org, string app, [FromQuer

if (formLayoutPayload.ComponentIdsChange is not null && !string.IsNullOrEmpty(layoutSetName))
{
foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange)
foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange.Where((componentIdChange) => componentIdChange.OldComponentId != componentIdChange.NewComponentId))
{
if (componentIdChange.NewComponentId == null)
{
await _mediator.Publish(new ComponentDeletedEvent
{
ComponentId = componentIdChange.OldComponentId,
LayoutSetName = layoutSetName,
EditingContext = editingContext
}, cancellationToken);
}
await _mediator.Publish(new ComponentIdChangedEvent
{
OldComponentId = componentIdChange.OldComponentId,
Expand Down Expand Up @@ -155,16 +165,26 @@ await _mediator.Publish(new LayoutPageAddedEvent
/// <param name="app">Application identifier which is unique within an organisation.</param>
/// <param name="layoutSetName">The name of the layout set the specific layout belongs to</param>
/// <param name="layoutName">The form layout to be deleted</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
/// <returns>A success message if the save was successful</returns>
[HttpDelete]
[Route("form-layout/{layoutName}")]
public ActionResult DeleteFormLayout(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName)
public async Task<ActionResult> DeleteFormLayout(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, CancellationToken cancellationToken)
{
try
{
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer);

await _mediator.Publish(new LayoutPageDeletedEvent
{
EditingContext = editingContext,
LayoutSetName = layoutSetName,
LayoutName = layoutName,
}, cancellationToken);

_appDevelopmentService.DeleteFormLayout(editingContext, layoutSetName, layoutName);

return Ok();
}
catch (FileNotFoundException exception)
Expand Down Expand Up @@ -398,13 +418,15 @@ public async Task<ActionResult> DeleteLayoutSet(string org, string app, [FromRou
{
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer);
LayoutSets layoutSets = await _appDevelopmentService.DeleteLayoutSet(editingContext, layoutSetIdToUpdate, cancellationToken);

await _mediator.Publish(new LayoutSetDeletedEvent
{
EditingContext = editingContext,
LayoutSetId = layoutSetIdToUpdate
LayoutSetName = layoutSetIdToUpdate
}, cancellationToken);

LayoutSets layoutSets = await _appDevelopmentService.DeleteLayoutSet(editingContext, layoutSetIdToUpdate, cancellationToken);

return Ok(layoutSets);
}

Expand Down
8 changes: 4 additions & 4 deletions backend/src/Designer/Controllers/ResourceAdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ public async Task<ActionResult<List<AvailableService>>> GetAltinn2LinkServices(s
foreach (ServiceResource resource in allResources)
{
if (resource?.HasCompetentAuthority.Orgcode != null
&& resource.ResourceReferences != null && resource.ResourceReferences.Exists(r => r.ReferenceType != null && r.ReferenceType.Equals(ReferenceType.ServiceCode))
&& resource.ResourceReferences != null && resource.ResourceReferences.Exists(r => r.ReferenceType != null && r.ReferenceType.Equals(ResourceReferenceType.ServiceCode))
&& resource.ResourceType == ResourceType.Altinn2Service)
{
AvailableService service = new AvailableService();
Expand All @@ -496,8 +496,8 @@ public async Task<ActionResult<List<AvailableService>>> GetAltinn2LinkServices(s
service.ServiceName = resource.Title["nb"];
}

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

if (resource.ResourceType == ResourceType.MaskinportenSchema)
{
if (resource.ResourceReferences == null || !resource.ResourceReferences.Any((x) => x.ReferenceType == ReferenceType.MaskinportenScope))
if (resource.ResourceReferences == null || !resource.ResourceReferences.Any((x) => x.ReferenceType == ResourceReferenceType.MaskinportenScope))
{
ModelState.AddModelError($"{resource.Identifier}.resourceReferences", "resourceerror.missingmaskinportenscope");
}
Expand Down
28 changes: 3 additions & 25 deletions backend/src/Designer/Enums/ReferenceType.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,9 @@
using System.Runtime.Serialization;

namespace Altinn.Studio.Designer.Enums
{
/// <summary>
/// Enum for reference types of resources in the resource registry
/// </summary>
public enum ReferenceType
{
[EnumMember(Value = "Default")]
Default = 0,

[EnumMember(Value = "Uri")]
Uri = 1,

[EnumMember(Value = "DelegationSchemeId")]
DelegationSchemeId = 2,

[EnumMember(Value = "MaskinportenScope")]
MaskinportenScope = 3,

[EnumMember(Value = "ServiceCode")]
ServiceCode = 4,

[EnumMember(Value = "ServiceEditionCode")]
ServiceEditionCode = 5,

[EnumMember(Value = "ApplicationId")]
ApplicationId = 6,
LayoutSet,
Layout,
Component
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Altinn.Studio.Designer.Enums
/// <summary>
/// Enum for the different reference sources for resources in the resource registry
/// </summary>
public enum ReferenceSource
public enum ResourceReferenceSource
{
[EnumMember(Value = "Default")]
Default = 0,
Expand Down
31 changes: 31 additions & 0 deletions backend/src/Designer/Enums/ResourceReferenceType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Runtime.Serialization;

namespace Altinn.Studio.Designer.Enums
{
/// <summary>
/// Enum for reference types of resources in the resource registry
/// </summary>
public enum ResourceReferenceType
{
[EnumMember(Value = "Default")]
Default = 0,

[EnumMember(Value = "Uri")]
Uri = 1,

[EnumMember(Value = "DelegationSchemeId")]
DelegationSchemeId = 2,

[EnumMember(Value = "MaskinportenScope")]
MaskinportenScope = 3,

[EnumMember(Value = "ServiceCode")]
ServiceCode = 4,

[EnumMember(Value = "ServiceEditionCode")]
ServiceEditionCode = 5,

[EnumMember(Value = "ApplicationId")]
ApplicationId = 6,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Enums;
using Altinn.Studio.Designer.Events;
using Altinn.Studio.Designer.Hubs.SyncHub;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Interfaces;
using MediatR;

namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted;

public class ComponentDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler<ComponentDeletedEvent>
{
public async Task Handle(ComponentDeletedEvent notification, CancellationToken cancellationToken)
{
await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
notification.EditingContext,
SyncErrorCodes.ComponentDeletedLayoutsSyncError,
"layouts",
async () =>
{
List<Reference> referencesToDelete = [new Reference(ReferenceType.Component, notification.LayoutSetName, notification.ComponentId)];
return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Enums;
using Altinn.Studio.Designer.Events;
using Altinn.Studio.Designer.Hubs.SyncHub;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Interfaces;
using MediatR;

namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted;

public class LayoutPageDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler<LayoutPageDeletedEvent>
{
public async Task Handle(LayoutPageDeletedEvent notification, CancellationToken cancellationToken)
{
await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
notification.EditingContext,
SyncErrorCodes.LayoutPageDeletedLayoutsSyncError,
"layouts",
async () =>
{
List<Reference> referencesToDelete = [new Reference(ReferenceType.Layout, notification.LayoutSetName, notification.LayoutName)];
return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken);
});
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Enums;
using Altinn.Studio.Designer.Events;
using Altinn.Studio.Designer.Hubs.SyncHub;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Interfaces;
using MediatR;

namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted;

public class LayoutSetDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler<LayoutSetDeletedEvent>
{
public async Task Handle(LayoutSetDeletedEvent notification, CancellationToken cancellationToken)
{
await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
notification.EditingContext,
SyncErrorCodes.LayoutSetDeletedLayoutsSyncError,
"layouts",
async () =>
{
List<Reference> referencesToDelete = [new Reference(ReferenceType.LayoutSet, notification.LayoutSetName, notification.LayoutSetName)];
return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken);
});
}
}
11 changes: 11 additions & 0 deletions backend/src/Designer/Events/ComponentDeletedEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Altinn.Studio.Designer.Models;
using MediatR;

namespace Altinn.Studio.Designer.Events;

public class ComponentDeletedEvent : INotification
{
public AltinnRepoEditingContext EditingContext { get; set; }
public string LayoutSetName { get; set; }
public string ComponentId { get; set; }
}
11 changes: 11 additions & 0 deletions backend/src/Designer/Events/LayoutPageDeletedEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Altinn.Studio.Designer.Models;
using MediatR;

namespace Altinn.Studio.Designer.Events;

public class LayoutPageDeletedEvent : INotification
{
public AltinnRepoEditingContext EditingContext { get; set; }
public string LayoutSetName { get; set; }
public string LayoutName { get; set; }
}
2 changes: 1 addition & 1 deletion backend/src/Designer/Events/LayoutSetDeletedEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Altinn.Studio.Designer.Events;

public class LayoutSetDeletedEvent : INotification
{
public string LayoutSetId { get; set; }
public AltinnRepoEditingContext EditingContext { get; set; }
public string LayoutSetName { get; set; }
}
4 changes: 3 additions & 1 deletion backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ public static class SyncErrorCodes
public const string ApplicationMetadataDataTypeSyncError = nameof(ApplicationMetadataDataTypeSyncError);
public const string LayoutSetsDataTypeSyncError = nameof(LayoutSetsDataTypeSyncError);
public const string LayoutSetComponentIdSyncError = nameof(LayoutSetComponentIdSyncError);
public const string LayoutSetSubLayoutSyncError = nameof(LayoutSetSubLayoutSyncError);
public const string LayoutSetDeletedLayoutsSyncError = nameof(LayoutSetDeletedLayoutsSyncError);
public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError);
public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError);
public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError);
public const string ComponentDeletedLayoutsSyncError = nameof(ComponentDeletedLayoutsSyncError);
public const string LayoutPageDeletedLayoutsSyncError = nameof(LayoutPageDeletedLayoutsSyncError);
}
7 changes: 7 additions & 0 deletions backend/src/Designer/Models/Reference.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

using Altinn.Studio.Designer.Enums;

namespace Altinn.Studio.Designer.Models
{
public record Reference(ReferenceType Type, string LayoutSetName, string Id, string NewId = null);
}
Loading
Loading