Skip to content

Commit

Permalink
Merge branch 'fix/12201_NotPossibleToDeleteFieldFromTypeInUse' of htt…
Browse files Browse the repository at this point in the history
…ps://github.com/Altinn/altinn-studio into fix/12201_NotPossibleToDeleteFieldFromTypeInUse
  • Loading branch information
Øvrelid committed Feb 2, 2024
2 parents 095323c + af5d2ef commit 98f3626
Show file tree
Hide file tree
Showing 589 changed files with 38,921 additions and 1,202 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ on:
- main
paths:
- 'frontend/**'
- '.github/workflow/playwright.yml'
workflow_dispatch:
- '.github/workflows/playwright.yml'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
playwright-run:
Expand Down Expand Up @@ -37,7 +40,7 @@ jobs:
restore-keys: |
${{ runner.os }}-yarn-
- name: Attempt to wait for deploy to environment (10 minutes sleep)
- name: Attempt to wait for deploy to environment (12 minutes sleep)
run: sleep 10m
shell: bash

Expand Down
28 changes: 28 additions & 0 deletions backend/src/Designer/Controllers/PreviewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ public IActionResult Index(string org, string app)
return View();
}

/// <summary>
/// Endpoint to fetch the cshtml to render app-frontend specific to what is defined in the app-repo
/// </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>
/// <returns>The cshtml modified to ignore this route path added in the iframe.</returns>
[HttpGet]
[Route("/app-specific-preview/{org}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}")]
public async Task<IActionResult> AppFrontendSpecificPreview(string org, string app)
{
string developer = AuthenticationHelper.GetDeveloperUserName(_httpContextAccessor.HttpContext);
AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
var appFrontendCshtml = await altinnAppGitRepository.GetAppFrontendCshtml();
var modifiedContent = ReplaceIndexToFetchCorrectOrgAppInCshtml(appFrontendCshtml);

return Content(modifiedContent, "text/html");
}

/// <summary>
/// Action for getting local app-images
/// </summary>
Expand Down Expand Up @@ -877,5 +895,15 @@ private string GetSelectedLayoutSetInEditorFromRefererHeader(string refererHeade

return string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
}

private string ReplaceIndexToFetchCorrectOrgAppInCshtml(string originalContent)
{
// Replace the array indexes in the script in the cshtml that retrieves the org and app name since
// /app-specific-preview/ is added when fetching the cshtml file from endpoint instead of designer wwwroot
string modifiedContent = originalContent.Replace("window.org = appId[1];", "window.org = appId[2];");
modifiedContent = modifiedContent.Replace("window.app = appId[2];", "window.app = appId[3];");

return modifiedContent;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class AltinnAppGitRepository : AltinnGitRepository
private const string LANGUAGE_RESOURCE_FOLDER_NAME = "texts/";
private const string MARKDOWN_TEXTS_FOLDER_NAME = "md/";
private const string PROCESS_DEFINITION_FOLDER_PATH = "App/config/process/";
private const string CSHTML_PATH = "App/views/Home/index.cshtml";

private const string SERVICE_CONFIG_FILENAME = "config.json";
private const string LAYOUT_SETTINGS_FILENAME = "Settings.json";
Expand Down Expand Up @@ -701,6 +702,23 @@ public async Task<LayoutSets> CreateLayoutSetFile(string layoutSetName)
return layoutSets;
}

/// <summary>
/// Gets the cshtml file for the app
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
/// <returns>The content of Index.cshtml</returns>
public async Task<string> GetAppFrontendCshtml(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
if (FileExistsByRelativePath(CSHTML_PATH))
{
string cshtml = await ReadTextByRelativePathAsync(CSHTML_PATH, cancellationToken);
return cshtml;
}

throw new FileNotFoundException("Index.cshtml was not found.");
}

/// <summary>
/// Gets the options list with the provided id.
/// <param name="optionsListId">The id of the options list to fetch.</param>
Expand Down Expand Up @@ -854,8 +872,6 @@ private static string GetPathToRuleConfiguration(string layoutSetName)
Path.Combine(LAYOUTS_FOLDER_NAME, layoutSetName, RULE_CONFIGURATION_FILENAME);
}



/// <summary>
/// String writer that ensures UTF8 is used.
/// </summary>
Expand Down
27 changes: 0 additions & 27 deletions backend/src/Designer/wwwroot/designer/html/preview.html

This file was deleted.

30 changes: 25 additions & 5 deletions frontend/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,48 @@
"plugin:react/recommended",
"plugin:react-hooks/recommended"
],
"plugins": ["jsx-a11y", "react", "react-hooks", "@typescript-eslint"],
"plugins": ["jsx-a11y", "react", "react-hooks", "@typescript-eslint", "import"],
"parser": "@typescript-eslint/parser",
"rules": {
"react/destructuring-assignment": "off",
"react/prop-types": "error",
"react/require-default-props": "off",
"import/prefer-default-export": "off",
"react/jsx-key": "error",
"react/jsx-filename-extension": ["warn", { "extensions": [".tsx"] }],
"react/jsx-filename-extension": [
"warn",
{
"extensions": [".tsx"]
}
],
"prefer-const": "error",
"object-curly-spacing": ["error", "always"],
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-explicit-any": "off"
"@typescript-eslint/no-explicit-any": "off",
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["**/libs/**"],
"message": "Use the package name, not the relative path, when importing from a @studio library."
}
]
}
]
},

"overrides": [
{
"files": ["*.tsx"],
"rules": {
"react/react-in-jsx-scope": "off",
"react/jsx-no-useless-fragment": ["error", { "allowExpressions": true }],
"react/jsx-no-useless-fragment": [
"error",
{
"allowExpressions": true
}
],
"no-use-before-define": "off",
"no-shadow": "off",
"react/function-component-definition": "off",
Expand Down
61 changes: 61 additions & 0 deletions frontend/app-development/router/routes.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { render, screen } from '@testing-library/react';
import { routerRoutes } from './routes';
import { RoutePaths } from '../enums/RoutePaths';
import React from 'react';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { QueryKey } from 'app-shared/types/QueryKey';
import type { AppVersion } from 'app-shared/types/AppVersion';
import { ServicesContextProvider } from 'app-shared/contexts/ServicesContext';
import { queriesMock } from 'app-shared/mocks/queriesMock';

// Mocks:
jest.mock('../../packages/ux-editor-v3/src/SubApp', () => ({
SubApp: () => <div data-testid='version 3' />,
}));
jest.mock('../../packages/ux-editor/src/SubApp', () => ({
SubApp: () => <div data-testid='latest version' />,
}));

// Test data
const org = 'org';
const app = 'app';

describe('routes', () => {
describe(RoutePaths.UIEditor, () => {
type FrontendVersion = null | '3.0.0' | '4.0.0';
type PackageVersion = 'version 3' | 'latest version';
type TestCase = [PackageVersion, FrontendVersion];

const testCases: TestCase[] = [
['version 3', null],
['version 3', '3.0.0'],
['latest version', '4.0.0'],
];

it.each(testCases)(
'Renders the %s schema editor page when the app frontend version is %s',
(expectedPackage, frontendVersion) => {
renderUiEditor(frontendVersion);
expect(screen.getByTestId(expectedPackage)).toBeInTheDocument();
},
);

const renderUiEditor = (frontendVersion: string | null) =>
renderSubapp(RoutePaths.UIEditor, frontendVersion);
});
});

const renderSubapp = (path: RoutePaths, frontendVersion: string = null) => {
const Subapp = routerRoutes.find((route) => route.path === path)!.subapp;
const appVersion: AppVersion = {
frontendVersion,
backendVersion: '7.0.0',
};
const queryClient = createQueryClientMock();
queryClient.setQueryData([QueryKey.AppVersion, org, app], appVersion);
return render(
<ServicesContextProvider {...queriesMock} client={queryClient}>
<Subapp />
</ServicesContextProvider>,
);
};
19 changes: 17 additions & 2 deletions frontend/app-development/router/routes.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { SubApp } from '../../packages/ux-editor/src/SubApp';
import { SubApp as UiEditorLatest } from '../../packages/ux-editor/src/SubApp';
import { SubApp as UiEditorV3 } from '../../packages/ux-editor-v3/src/SubApp';
import { Overview } from '../features/overview/components/Overview';
import { TextEditor } from '../features/textEditor/TextEditor';
import DataModellingContainer from '../features/dataModelling/containers/DataModellingContainer';
import { DeployPage } from '../features/appPublish/pages/deployPage';
import { ProcessEditor } from 'app-development/features/processEditor';
import { RoutePaths } from 'app-development/enums/RoutePaths';
import type { AppVersion } from 'app-shared/types/AppVersion';
import { useStudioUrlParams } from 'app-shared/hooks/useStudioUrlParams';
import { useAppVersionQuery } from 'app-shared/hooks/queries';
import React from 'react';

interface IRouteProps {
headerTextKey?: string;
Expand All @@ -25,10 +30,20 @@ interface RouterRoute {
props?: IRouteProps;
}

const latestFrontendVersion = '4';
const isLatestFrontendVersion = (version: AppVersion): boolean =>
version?.frontendVersion?.startsWith(latestFrontendVersion);

const UiEditor = () => {
const { org, app } = useStudioUrlParams();
const { data } = useAppVersionQuery(org, app);
return isLatestFrontendVersion(data) ? <UiEditorLatest /> : <UiEditorV3 />;
};

export const routerRoutes: RouterRoute[] = [
{
path: RoutePaths.UIEditor,
subapp: SubApp,
subapp: UiEditor,
},
{
path: RoutePaths.Overview,
Expand Down
10 changes: 8 additions & 2 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const config = {
},
transformIgnorePatterns: [
`node_modules(\\\\|/)(?!${packagesToTransform})`,
'frontend/packages/ux-editor/src/testing/schemas/',
'\\.schema\\.v1\\.json$',
'nb.json$',
'en.json$',
],
reporters: ['default', 'jest-junit'],
moduleNameMapper: {
Expand All @@ -44,6 +46,7 @@ const config = {
'^@altinn/schema-editor/(.*)': path.join(__dirname, 'packages/schema-editor/src/$1'),
'^@altinn/schema-model/(.*)': path.join(__dirname, 'packages/schema-model/src/$1'),
'^@altinn/ux-editor/(.*)': path.join(__dirname, 'packages/ux-editor/src/$1'),
'^@altinn/ux-editor-v3/(.*)': path.join(__dirname, 'packages/ux-editor-v3/src/$1'),
'^@altinn/process-editor/(.*)': path.join(__dirname, 'packages/process-editor/src/$1'),
'^@altinn/policy-editor/(.*)': path.join(__dirname, 'packages/policy-editor/src/$1'),
'^@studio/icons': path.join(__dirname, 'libs/studio-icons/src/$1'),
Expand All @@ -60,6 +63,9 @@ if (process.env.CI) {
config.reporters.push('github-actions');
config.collectCoverage = true;
config.coverageReporters = ['lcov'];
config.coveragePathIgnorePatterns = ['frontend/packages/ux-editor/src/testing/'];
config.coveragePathIgnorePatterns = [
'frontend/packages/ux-editor/src/testing/',
'frontend/packages/ux-editor-v3/src/testing/',
];
}
module.exports = config;
5 changes: 4 additions & 1 deletion frontend/language/src/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@
"left_menu.pages_error_format": "Must consist of letters (a-z), numbers, or \"-\", \"_\" and \".\"",
"left_menu.pages_error_length": "Can not be more than 30 characters",
"left_menu.pages_error_unique": "Must be unique",
"local_changes.modal_download_only_changed_button": "Download zip-file with only locally changed files.",
"local_changes_modal.download_all_button": "Download zip-file of the entire repo.",
"merge_conflict.body1": "There are breaking changes in the application that blocks further work.",
"merge_conflict.body2": "You can fix these by either download the application as a zip-file and delete the changes, or just blast the application directly.",
"merge_conflict.download": "Download",
Expand Down Expand Up @@ -918,6 +920,7 @@
"sync_header.no_changes_to_share": "Push",
"sync_header.nothing_to_push": "You have pushed your latest changes",
"sync_header.repo_is_offline": "Repo is offline",
"sync_header.repository": "Repository",
"sync_header.service_updated_to_latest": "Your app is updated to the latest version",
"sync_header.service_updated_to_latest_submessage": "It is important to fetch changes often if there are multiple people working on the same app. This reduces the chances of merge conflicts.",
"sync_header.share_changes": "Push",
Expand All @@ -932,6 +935,7 @@
"testing.testing_in_testenv_title": "Testing in test environment",
"top_menu.about": "About",
"top_menu.create": "Create",
"top_menu.dashboard": "Dashboard",
"top_menu.datamodel": "Data model",
"top_menu.deploy": "Deploy",
"top_menu.policy-editor": "Policy",
Expand Down Expand Up @@ -987,7 +991,6 @@
"ux_editor.component_dropdown_set_preselected": "Set pre-selected value in dropdown list",
"ux_editor.component_file_upload": "Attachment",
"ux_editor.component_group": "Group",
"ux_editor.component_group_header": "Group - {{id}}",
"ux_editor.component_header": "Title",
"ux_editor.component_image": "Image",
"ux_editor.component_information_panel": "Informative message",
Expand Down
4 changes: 3 additions & 1 deletion frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,7 @@
"schema_editor.import": "Importer",
"schema_editor.in_use_error": "Kan ikke slettes, er i bruk.",
"schema_editor.integer": "Heltall",
"schema_editor.invalid_child_error": "Det er ikke mulig å plassere den komponenttypen i denne gruppen.",
"schema_editor.keyword": "Nøkkelord",
"schema_editor.language": "Språk",
"schema_editor.language_add_language": "Legg til språk:",
Expand Down Expand Up @@ -1265,6 +1266,7 @@
"sync_header.no_changes_to_share": "Last opp dine endringer",
"sync_header.nothing_to_push": "Du har delt dine siste endringer",
"sync_header.repo_is_offline": "Repo er utilgjengelig",
"sync_header.repository": "Repository",
"sync_header.service_updated_to_latest": "Appen din er oppdatert til siste versjon",
"sync_header.service_updated_to_latest_submessage": "Hvis det er flere personer som jobber på samme app er det viktig å hente endringer ofte. På denne måten reduserer du sjansen for mergekonflikter.",
"sync_header.settings": "Innstillinger",
Expand All @@ -1290,6 +1292,7 @@
"text_editor.variables_editing_not_supported": "Det, er ikke lagt til støtte for redigering av variabler i Studio.",
"top_menu.about": "Oversikt",
"top_menu.create": "Lage",
"top_menu.dashboard": "Dashboard",
"top_menu.datamodel": "Datamodell",
"top_menu.deploy": "Publiser",
"top_menu.preview": "Forhåndsvis",
Expand Down Expand Up @@ -1341,7 +1344,6 @@
"ux_editor.component_deletion_confirm": "Ja, slett komponenten",
"ux_editor.component_deletion_text": "Er du sikker på at du vil slette denne komponenten?",
"ux_editor.component_dropdown_set_preselected": "Sett forhåndsvalgt verdi for nedtrekksliste",
"ux_editor.component_group_header": "Gruppe - {{id}}",
"ux_editor.component_help_text.Accordion": "Med Accordion kan du presentere mye innhold på liten plass i en eller flere rader. Hele raden er klikkbar og lar brukere åpne eller lukke visningen av innholdet under.",
"ux_editor.component_help_text.AccordionGroup": "En samling med Accordions som vises vertikalt. Brukes for å gruppere Accordions som hører sammen.",
"ux_editor.component_help_text.ActionButton": "Knapp for å trigge en spesifisert aksjon knyttet til prosess-steget sluttbruker befinner seg i. Eksempler inkluderer 'sign', 'confirm', 'reject'.",
Expand Down
Loading

0 comments on commit 98f3626

Please sign in to comment.