Skip to content

Commit

Permalink
feat: Delete all Summary 2.0 components that has a reference to a del…
Browse files Browse the repository at this point in the history
…eted layout
  • Loading branch information
mlqn committed Dec 2, 2024
1 parent ea8ca6c commit d142c3e
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 1 deletion.
11 changes: 10 additions & 1 deletion backend/src/Designer/Controllers/AppDevelopmentController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,24 @@ 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();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Events;
using Altinn.Studio.Designer.Hubs.SyncHub;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Interfaces;
using MediatR;
using System.Text.Json.Nodes;
using Altinn.App.Core.Helpers;

namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted;

public class LayoutPageDeletedHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory,
IFileSyncHandlerExecutor fileSyncHandlerExecutor) : INotificationHandler<LayoutPageDeletedEvent>
{
public async Task Handle(LayoutPageDeletedEvent notification, CancellationToken cancellationToken)
{
AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(
notification.EditingContext.Org,
notification.EditingContext.Repo,
notification.EditingContext.Developer);

LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken);

await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification(
notification.EditingContext,
SyncErrorCodes.LayoutPageDeletedSyncError,
"layouts",
async () =>
{
bool hasChanges = false;
foreach (LayoutSetConfig layoutSet in layoutSets.Sets)
{
Dictionary<string, JsonNode> formLayouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken);
foreach (var formLayout in formLayouts)
{
hasChanges |= await RemoveComponentsReferencingLayout(
notification,
altinnAppGitRepository,
layoutSets.Sets,
layoutSet.Id,
formLayout,
cancellationToken);
}
}
return hasChanges;
});
}

private static async Task<bool> RemoveComponentsReferencingLayout(LayoutPageDeletedEvent notification, AltinnAppGitRepository altinnAppGitRepository, List<LayoutSetConfig> layoutSets, string layoutSetName, KeyValuePair<string, JsonNode> formLayout, CancellationToken cancellationToken)
{
if (formLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray)
{
return false;
}

bool hasChanges = false;
layoutArray.RemoveAll(jsonNode =>
{
if (jsonNode["type"]?.GetValue<string>() == "Summary2" && jsonNode["target"] is JsonObject targetObject)
{
string summaryType = targetObject["type"]?.GetValue<string>();
string taskId = targetObject["taskId"]?.GetValue<string>();
string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSetName : layoutSets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id;
bool hasLayoutSet = summaryType == "layout" && layouSetId == notification.LayoutSetName;
if (hasLayoutSet)
{
hasChanges = true;
return true;
}
}
return false;
});

if (hasChanges)
{
await altinnAppGitRepository.SaveLayout(layoutSetName, $"{formLayout.Key}.json", formLayout.Value, cancellationToken);
}
return hasChanges;
}
}
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; }
}
1 change: 1 addition & 0 deletions backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public static class SyncErrorCodes
public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError);
public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError);
public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError);
public const string LayoutPageDeletedSyncError = nameof(LayoutPageDeletedSyncError);
}

0 comments on commit d142c3e

Please sign in to comment.