Skip to content

Commit

Permalink
Merge branch 'main' into 12787-resizable-layout-component
Browse files Browse the repository at this point in the history
Merge
  • Loading branch information
Jondyr committed Jul 11, 2024
2 parents 6421dc0 + 8f7cdec commit 7f1b23e
Show file tree
Hide file tree
Showing 337 changed files with 572 additions and 419 deletions.
7 changes: 4 additions & 3 deletions backend/src/Designer/Controllers/AppDevelopmentController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,16 +326,17 @@ public async Task<IActionResult> GetLayoutSets(string org, string app, Cancellat
/// </summary>
/// <param name="org">Unique identifier of the organisation responsible for the app.</param>
/// <param name="app">Application identifier which is unique within an organisation.</param>
/// <param name="layoutSet">The config needed for the layout set to be added to layout-sets.json</param>
/// <param name="layoutSetPayload">Includes the connected taskType and the actual config needed for the layout set to be added to layout-sets.json.</param>
/// <param name="cancellationToken">An <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
[HttpPost]
[UseSystemTextJson]
[Route("layout-set/{layoutSetIdToUpdate}")]
public async Task<ActionResult> AddLayoutSet(string org, string app, [FromBody] LayoutSetConfig layoutSet, CancellationToken cancellationToken)
public async Task<ActionResult> AddLayoutSet(string org, string app, [FromBody] LayoutSetPayload layoutSetPayload, CancellationToken cancellationToken)
{
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer);
LayoutSets layoutSets = await _appDevelopmentService.AddLayoutSet(editingContext, layoutSet, cancellationToken);
bool layoutIsInitialForPaymentTask = layoutSetPayload.TaskType == TaskType.Payment;
LayoutSets layoutSets = await _appDevelopmentService.AddLayoutSet(editingContext, layoutSetPayload.LayoutSetConfig, layoutIsInitialForPaymentTask, cancellationToken);
return Ok(layoutSets);
}

Expand Down
12 changes: 12 additions & 0 deletions backend/src/Designer/Models/Dto/LayoutSetPayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
using JetBrains.Annotations;

namespace Altinn.Studio.Designer.Models.Dto;

public class LayoutSetPayload
{
[JsonPropertyName("taskType")]
[CanBeNull] public string TaskType { get; set; }
[JsonPropertyName("LayoutSetConfig")]
public LayoutSetConfig LayoutSetConfig { get; set; }
}
6 changes: 6 additions & 0 deletions backend/src/Designer/Models/TaskType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Altinn.Studio.Designer.Models;

public static class TaskType
{
public const string Payment = "payment";
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public async Task<LayoutSetConfig> GetLayoutSetConfig(AltinnRepoEditingContext a

/// <inheritdoc />
public async Task<LayoutSets> AddLayoutSet(AltinnRepoEditingContext altinnRepoEditingContext,
LayoutSetConfig newLayoutSet, CancellationToken cancellationToken = default)
LayoutSetConfig newLayoutSet, bool layoutIsInitialForPaymentTask = false, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
AltinnAppGitRepository altinnAppGitRepository =
Expand All @@ -310,7 +310,7 @@ public async Task<LayoutSets> AddLayoutSet(AltinnRepoEditingContext altinnRepoEd
throw new NonUniqueTaskForLayoutSetException($"Layout set with task, {newLayoutSet.Tasks[0]}, already exists.");
}

return await AddNewLayoutSet(altinnAppGitRepository, layoutSets, newLayoutSet);
return await AddNewLayoutSet(altinnAppGitRepository, layoutSets, newLayoutSet, layoutIsInitialForPaymentTask);
}

/// <inheritdoc />
Expand Down Expand Up @@ -376,9 +376,13 @@ private static async Task<LayoutSets> DeleteExistingLayoutSet(AltinnAppGitReposi
return layoutSets;
}

private static async Task<LayoutSets> AddNewLayoutSet(AltinnAppGitRepository altinnAppGitRepository, LayoutSets layoutSets, LayoutSetConfig layoutSet)
private static async Task<LayoutSets> AddNewLayoutSet(AltinnAppGitRepository altinnAppGitRepository, LayoutSets layoutSets, LayoutSetConfig layoutSet, bool layoutIsInitialForPaymentTask = false)
{
layoutSets.Sets.Add(layoutSet);
if (layoutIsInitialForPaymentTask)
{
AddPaymentComponentToInitialLayoutForPaymentTask(altinnAppGitRepository.InitialLayout);
}
await altinnAppGitRepository.SaveLayout(layoutSet.Id, AltinnAppGitRepository.InitialLayoutFileName,
altinnAppGitRepository.InitialLayout);
await altinnAppGitRepository.SaveLayoutSettings(layoutSet.Id,
Expand All @@ -387,6 +391,21 @@ await altinnAppGitRepository.SaveLayoutSettings(layoutSet.Id,
return layoutSets;
}

private static void AddPaymentComponentToInitialLayoutForPaymentTask(JsonNode layout)
{
var layoutArray = layout["data"]["layout"] as JsonArray;
if (layoutArray != null)
{
var defaultComponent = new JsonObject
{
["id"] = "PaymentComponentId",
["type"] = TaskType.Payment,
["renderAsSummary"] = true
};
layoutArray.Add(defaultComponent);
}
}

private async Task<LayoutSets> UpdateLayoutSetName(AltinnAppGitRepository altinnAppGitRepository, LayoutSets layoutSets, string oldLayoutSetName, string newLayoutSetName)
{
layoutSets.Sets.Find(set => set.Id == oldLayoutSetName).Id = newLayoutSetName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,10 @@ public Task<ModelMetadata> GetModelMetadata(
/// </summary>
/// <param name="altinnRepoEditingContext">An <see cref="AltinnRepoEditingContext"/>.</param>
/// <param name="newLayoutSet">Config for the new layout set</param>
/// <param name="layoutIsInitialForPaymentTask">Boolean value indicating if the layout set is the initial layout set for a payment task.
/// Default is false if not specified </param>
/// <param name="cancellationToken">An <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
public Task<LayoutSets> AddLayoutSet(AltinnRepoEditingContext altinnRepoEditingContext, LayoutSetConfig newLayoutSet, CancellationToken cancellationToken = default);
public Task<LayoutSets> AddLayoutSet(AltinnRepoEditingContext altinnRepoEditingContext, LayoutSetConfig newLayoutSet, bool layoutIsInitialForPaymentTask = false, CancellationToken cancellationToken = default);

/// <summary>
/// Updates an existing layout set with a new layout set id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Factories;
using Altinn.Studio.Designer.Filters;
using Altinn.Studio.Designer.Filters.AppDevelopment;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.Services.Implementation;
using Designer.Tests.Controllers.ApiTests;
using Designer.Tests.Utils;
using FluentAssertions;
Expand All @@ -33,13 +37,16 @@ public async Task AddLayoutSets_NewSet_ReturnsOk(string org, string app, string
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);
var newLayoutSetConfig = new LayoutSetConfig() { Id = layoutSetId, Tasks = ["NewTask"] };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = "data", LayoutSetConfig = newLayoutSetConfig };

LayoutSets layoutSetsBefore = await GetLayoutSetsFile(org, targetRepository, developer);

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(newLayoutSetConfig), Encoding.UTF8, "application/json")
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
Expand All @@ -62,12 +69,14 @@ public async Task AddLayoutSet_NewLayoutSetIdExistsBefore_ReturnsOKButWithConfli
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);
var newLayoutSetConfig = new LayoutSetConfig() { Id = layoutSetId, Tasks = ["newTask"] };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = "data", LayoutSetConfig = newLayoutSetConfig };

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(newLayoutSetConfig), Encoding.UTF8, "application/json")
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
Expand All @@ -86,12 +95,14 @@ public async Task AddLayoutSet_NewLayoutSetTaskIdExistsBefore_ReturnsOKButWithCo
await CopyRepositoryForTest(org, app, developer, targetRepository);
const string existingTaskId = "Task_1";
var newLayoutSetConfig = new LayoutSetConfig() { Id = layoutSetId, Tasks = [existingTaskId] };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = "data", LayoutSetConfig = newLayoutSetConfig };

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(newLayoutSetConfig), Encoding.UTF8, "application/json")
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
Expand All @@ -109,32 +120,93 @@ public async Task AddLayoutSet_NewLayoutSetIdIsEmpty_ReturnsBadRequest(string or
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);
var newLayoutSetConfig = new LayoutSetConfig() { Id = "" };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = "data", LayoutSetConfig = newLayoutSetConfig };

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(newLayoutSetConfig), Encoding.UTF8, "application/json")
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}

[Theory]
[InlineData("ttd", "app-with-layoutsets", "testUser", "newSet")]
public async Task AddLayoutSet_TaskTypeIsNull_AddsLayoutSetAndReturnsOk(string org, string app, string developer,
string layoutSetId)
{
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);
var newLayoutSetConfig = new LayoutSetConfig() { Id = layoutSetId, Tasks = ["NewTask"] };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = null, LayoutSetConfig = newLayoutSetConfig };

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}

[Theory]
[InlineData("ttd", "app-with-layoutsets", "testUser", "newSet")]
public async Task AddLayoutSet_TaskTypeIsPayment_AddsLayoutSetWithPaymentComponentInInitialLayoutAndReturnsOk(string org, string app, string developer,
string layoutSetId)
{
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);
var newLayoutSetConfig = new LayoutSetConfig() { Id = layoutSetId, Tasks = ["NewTask"] };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = TaskType.Payment, LayoutSetConfig = newLayoutSetConfig };

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
response.StatusCode.Should().Be(HttpStatusCode.OK);

JsonNode initialLayout = await GetLayoutFile(org, targetRepository, developer, layoutSetId);

var defaultComponent = new JsonObject
{
["id"] = "PaymentComponentId",
["type"] = "Payment",
["renderAsSummary"] = true
};

JsonArray layout = initialLayout["data"]["layout"] as JsonArray;
layout.Count.Should().Be(1);
initialLayout["data"]["layout"][0].Should().BeEquivalentTo(defaultComponent, options => options.RespectingRuntimeTypes().IgnoringCyclicReferences());
}

[Theory]
[InlineData("ttd", "app-without-layoutsets", "testUser", null)]
public async Task AddLayoutSet_AppWithoutLayoutSets_ReturnsNotFound(string org, string app, string developer,
string layoutSetId)
{
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);
var newLayoutSetConfig = new LayoutSetConfig() { Id = "newSet" };
var newLayoutSetConfig = new LayoutSetConfig() { Id = layoutSetId, Tasks = ["NewTask"] };
LayoutSetPayload layoutSetPayload = new LayoutSetPayload()
{ TaskType = "data", LayoutSetConfig = newLayoutSetConfig };

string url = $"{VersionPrefix(org, targetRepository)}/layout-set/{layoutSetId}";

using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonSerializer.Serialize(newLayoutSetConfig), Encoding.UTF8, "application/json")
Content = new StringContent(JsonSerializer.Serialize(layoutSetPayload), Encoding.UTF8, "application/json")
};

using var response = await HttpClient.SendAsync(httpRequestMessage);
Expand All @@ -151,6 +223,15 @@ private async Task<LayoutSets> GetLayoutSetsFile(string org, string app, string
return await altinnAppGitRepository.GetLayoutSetsFile();
}

private async Task<JsonNode> GetLayoutFile(string org, string app, string developer, string layoutSetName)
{
AltinnGitRepositoryFactory altinnGitRepositoryFactory =
new(TestDataHelper.GetTestDataRepositoriesRootDirectory());
AltinnAppGitRepository altinnAppGitRepository =
altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);

return await altinnAppGitRepository.GetLayout(layoutSetName, AltinnAppGitRepository.InitialLayoutFileName);
}
}
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import classes from './CreateRelease.module.css';
import type { ChangeEvent } from 'react';
import { Textfield, Textarea } from '@digdir/design-system-react';
import { Textfield, Textarea } from '@digdir/designsystemet-react';
import { versionNameValid } from './utils';
import { useBranchStatusQuery, useAppReleasesQuery } from '../../../hooks/queries';
import { useCreateReleaseMutation } from '../../../hooks/mutations';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCreateDeploymentMutation } from '../../../hooks/mutations';
import { Trans, useTranslation } from 'react-i18next';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { toast } from 'react-toastify';
import { Alert, Link } from '@digdir/design-system-react';
import { Alert, Link } from '@digdir/designsystemet-react';
import { useDeployPermissionsQuery } from 'app-development/hooks/queries';
import { StudioSpinner } from '@studio/components';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from 'react';
import classes from './DeployDropdown.module.css';
import { AltinnConfirmDialog } from 'app-shared/components';
import { StudioButton, StudioSpinner } from '@studio/components';
import { Alert, Combobox, Spinner } from '@digdir/design-system-react';
import { Alert, Combobox, Spinner } from '@digdir/designsystemet-react';
import type { ImageOption } from './ImageOption';
import { useTranslation } from 'react-i18next';
import { useAppReleasesQuery } from 'app-development/hooks/queries';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import classes from './DeploymentEnvironmentLogList.module.css';
import { Heading, Link, Table } from '@digdir/design-system-react';
import { Heading, Link, Table } from '@digdir/designsystemet-react';
import { DateUtils } from '@studio/pure-functions';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import classes from './DeploymentEnvironmentStatus.module.css';
import { Alert, Heading, Link, Paragraph, Spinner } from '@digdir/design-system-react';
import { Alert, Heading, Link, Paragraph, Spinner } from '@digdir/designsystemet-react';
import { Trans, useTranslation } from 'react-i18next';
import type { KubernetesDeployment } from 'app-shared/types/api/KubernetesDeployment';
import { DateUtils } from '@studio/pure-functions';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmen
import { DeploymentEnvironment } from '../components/DeploymentEnvironment';
import { getAppLink } from 'app-shared/ext-urls';
import { useTranslation } from 'react-i18next';
import { Alert } from '@digdir/design-system-react';
import { Alert } from '@digdir/designsystemet-react';
import { PROD_ENV_TYPE } from 'app-shared/constants';

export const DeploymentContainer = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Trans, useTranslation } from 'react-i18next';
import { AltinnContentLoader } from 'app-shared/components/molecules/AltinnContentLoader';
import { useInvalidator } from '../../../hooks/useInvalidator';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { Alert } from '@digdir/design-system-react';
import { Alert } from '@digdir/designsystemet-react';

export function DeployPage() {
const { org, app } = useStudioEnvironmentParams();
Expand Down
Loading

0 comments on commit 7f1b23e

Please sign in to comment.