| undefined;
diff --git a/src/features/instantiate/containers/InstantiateValidationError.tsx b/src/features/instantiate/containers/InstantiateValidationError.tsx
index 65f3cc999d..8a58c2cbc0 100644
--- a/src/features/instantiate/containers/InstantiateValidationError.tsx
+++ b/src/features/instantiate/containers/InstantiateValidationError.tsx
@@ -7,25 +7,20 @@ import { useLanguage } from 'src/features/language/useLanguage';
export function InstantiateValidationError(props: { message: string }) {
const { langAsString } = useLanguage();
- function createErrorContent() {
- const errorCustomerService = langAsString(
- 'instantiate.authorization_error_instantiate_validation_info_customer_service',
- [langAsString('general.customer_service_phone_number')],
- );
- return (
- <>
- {props.message && }
-
-
- {errorCustomerService}
- >
- );
- }
-
return (
}
- content={createErrorContent()}
+ content={
+ <>
+ {props.message && }
+
+
+
+ >
+ }
statusCode={`${langAsString('party_selection.error_caption_prefix')} 403`}
/>
);
diff --git a/src/features/instantiate/selection/InstanceSelection.module.css b/src/features/instantiate/selection/InstanceSelection.module.css
index d2ecf3330a..cf41f1dbae 100644
--- a/src/features/instantiate/selection/InstanceSelection.module.css
+++ b/src/features/instantiate/selection/InstanceSelection.module.css
@@ -19,11 +19,6 @@
TODO(1779): Remove these styles after going through all the different Table styles in
Altinn, and making sure they are consistent. */
-.table {
- box-shadow:
- 0 1px 1px rgba(0, 0, 0, 0.12),
- 0 2px 2px rgba(0, 0, 0, 0.12);
-}
@media (max-width: 992px) {
.table {
border-top: 1px solid #dde3e5;
diff --git a/src/features/instantiate/selection/InstanceSelection.tsx b/src/features/instantiate/selection/InstanceSelection.tsx
index ba4d3e7fe0..3a13ca8fc9 100644
--- a/src/features/instantiate/selection/InstanceSelection.tsx
+++ b/src/features/instantiate/selection/InstanceSelection.tsx
@@ -7,13 +7,14 @@ import { PencilIcon } from '@navikt/aksel-icons';
import { Button } from 'src/app-components/Button/Button';
import { Pagination } from 'src/app-components/Pagination/Pagination';
+import { ErrorListFromInstantiation, ErrorReport } from 'src/components/message/ErrorReport';
import { PresentationComponent } from 'src/components/presentation/Presentation';
import { ReadyForPrint } from 'src/components/ReadyForPrint';
import { useIsProcessing } from 'src/core/contexts/processingContext';
import { TaskStoreProvider } from 'src/core/contexts/taskStoreContext';
import { useAppName, useAppOwner } from 'src/core/texts/appTexts';
import { useApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
-import { useInstantiation } from 'src/features/instantiate/InstantiationContext';
+import { useClearInstantiation, useInstantiation } from 'src/features/instantiate/InstantiationContext';
import {
ActiveInstancesProvider,
useActiveInstances,
@@ -64,7 +65,7 @@ function InstanceSelection() {
const { langAsString } = useLanguage();
const mobileView = useIsMobileOrTablet();
const rowsPerPageOptions = instanceSelectionOptions?.rowsPerPageOptions ?? [10, 25, 50];
- const instantiate = useInstantiation().instantiate;
+ const instantiation = useInstantiation();
const currentParty = useCurrentParty();
const storeCallback = useSetNavigationEffect();
const { performProcess, isAnyProcessing, isThisProcessing: isLoading } = useIsProcessing();
@@ -82,6 +83,8 @@ function InstanceSelection() {
const instances = instanceSelectionOptions?.sortDirection === 'desc' ? [..._instances].reverse() : _instances;
const paginatedInstances = instances.slice(currentPage * rowsPerPage, (currentPage + 1) * rowsPerPage);
+ useClearInstantiation();
+
function handleRowsPerPageChanged(newRowsPerPage: number) {
setRowsPerPage(newRowsPerPage);
if (instances.length < currentPage * newRowsPerPage) {
@@ -267,22 +270,27 @@ function InstanceSelection() {
{mobileView && renderMobileTable()}
{!mobileView && renderTable()}
-
+
+
diff --git a/src/layout/InstantiationButton/InstantiationButton.module.css b/src/layout/InstantiationButton/InstantiationButton.module.css
index b8cbf4a239..7a46cf133b 100644
--- a/src/layout/InstantiationButton/InstantiationButton.module.css
+++ b/src/layout/InstantiationButton/InstantiationButton.module.css
@@ -1,4 +1,5 @@
.container {
display: flex;
gap: var(--button-gap);
+ width: 100%;
}
diff --git a/src/layout/InstantiationButton/InstantiationButton.tsx b/src/layout/InstantiationButton/InstantiationButton.tsx
index 59c731b02d..14bbb9213e 100644
--- a/src/layout/InstantiationButton/InstantiationButton.tsx
+++ b/src/layout/InstantiationButton/InstantiationButton.tsx
@@ -1,6 +1,7 @@
-import React, { useEffect } from 'react';
+import React from 'react';
import { Button } from 'src/app-components/Button/Button';
+import { ErrorListFromInstantiation, ErrorReport } from 'src/components/message/ErrorReport';
import { useIsProcessing } from 'src/core/contexts/processingContext';
import { DataModels } from 'src/features/datamodel/DataModelsProvider';
import { FD } from 'src/features/formData/FormDataWrite';
@@ -12,46 +13,36 @@ type Props = Omit {
- const { instantiateWithPrefill, error } = useInstantiation();
+ const instantiation = useInstantiation();
const { performProcess, isAnyProcessing, isThisProcessing: isLoading } = useIsProcessing();
const prefill = FD.useMapping(props.mapping, DataModels.useDefaultDataType());
const party = useCurrentParty();
- // const onClick = () => {
- // instantiateWithPrefill(props.node, {
- // prefill,
- // instanceOwner: {
- // partyId: party?.partyId.toString(),
- // },
- // });
- // };
-
- useEffect(() => {
- if (error) {
- throw error;
- }
- }, [error]);
-
return (
-
+
+
);
};
diff --git a/test/e2e/integration/frontend-test/instantiation.ts b/test/e2e/integration/frontend-test/instantiation.ts
new file mode 100644
index 0000000000..dd185c4db9
--- /dev/null
+++ b/test/e2e/integration/frontend-test/instantiation.ts
@@ -0,0 +1,52 @@
+import { AppFrontend } from 'test/e2e/pageobjects/app-frontend';
+import { cyMockResponses } from 'test/e2e/pageobjects/party-mocks';
+
+const appFrontend = new AppFrontend();
+
+describe('Instantiation', () => {
+ // See ttd/frontend-test/App/logic/Instantiation/InstantiationValidator.cs
+ const invalidParty =
+ Cypress.env('type') === 'localtest'
+ ? /950474084/ // Localtest: Oslos Vakreste borettslag
+ : /310732001/; // TT02: Søvnig Impulsiv Tiger AS
+
+ it('should show an error message when going directly to instantiation', () => {
+ cyMockResponses({
+ doNotPromptForParty: false,
+ onEntryShow: 'new-instance',
+ });
+ cy.startAppInstance(appFrontend.apps.frontendTest, { user: 'manager' });
+ cy.findByRole('button', { name: invalidParty }).click();
+
+ cy.findByText('Du kan ikke starte denne tjenesten').should('be.visible');
+ assertErrorMessage();
+ });
+
+ it('should show an error message when starting a new instance from instance-selection', () => {
+ cyMockResponses({
+ doNotPromptForParty: false,
+ onEntryShow: 'select-instance',
+ activeInstances: [
+ { id: 'abc123', lastChanged: '2023-01-01T00:00:00.000Z', lastChangedBy: 'user' },
+ { id: 'def456', lastChanged: '2023-01-02T00:00:00.000Z', lastChangedBy: 'user' },
+ ],
+ });
+ cy.startAppInstance(appFrontend.apps.frontendTest, { user: 'manager' });
+ cy.findByRole('button', { name: invalidParty }).click();
+
+ cy.findByText('Du har allerede startet å fylle ut dette skjemaet.').should('be.visible');
+ cy.findByRole('button', { name: 'Start på nytt' }).click();
+
+ assertErrorMessage();
+ cy.findByText('Du kan ikke starte denne tjenesten').should('not.exist');
+ });
+
+ function assertErrorMessage() {
+ cy.findByText(
+ /Aktøren du valgte kan ikke opprette en instans av dette skjemaet. Dette er en egendefinert feilmelding for akkurat denne appen./,
+ ).should('be.visible');
+ cy.findByRole('link', { name: 'Vennligst velg en annen aktør' }).click();
+
+ cy.findByRole('button', { name: invalidParty }).should('be.visible');
+ }
+});
diff --git a/test/e2e/pageobjects/party-mocks.ts b/test/e2e/pageobjects/party-mocks.ts
index f4146ca53b..89cc7d9a1d 100644
--- a/test/e2e/pageobjects/party-mocks.ts
+++ b/test/e2e/pageobjects/party-mocks.ts
@@ -1,5 +1,6 @@
import { PartyType } from 'src/types/shared';
-import type { IncomingApplicationMetadata } from 'src/features/applicationMetadata/types';
+import type { IncomingApplicationMetadata, ShowTypes } from 'src/features/applicationMetadata/types';
+import type { ISimpleInstance } from 'src/types';
import type { IParty } from 'src/types/shared';
const ExampleOrgWithSubUnit: IParty = {
@@ -100,7 +101,8 @@ interface Mockable {
doNotPromptForParty?: boolean;
appPromptForPartyOverride?: IncomingApplicationMetadata['promptForParty'];
partyTypesAllowed?: IncomingApplicationMetadata['partyTypesAllowed'];
- noActiveInstances?: boolean; // Defaults to true
+ activeInstances?: false | ISimpleInstance[]; // Defaults to false
+ onEntryShow?: ShowTypes;
}
export function cyMockResponses(whatToMock: Mockable) {
@@ -138,22 +140,28 @@ export function cyMockResponses(whatToMock: Mockable) {
},
});
}
- if (whatToMock.appPromptForPartyOverride !== undefined || whatToMock.partyTypesAllowed !== undefined) {
+ if (
+ whatToMock.appPromptForPartyOverride !== undefined ||
+ whatToMock.partyTypesAllowed !== undefined ||
+ whatToMock.onEntryShow !== undefined
+ ) {
cy.intercept('GET', '**/api/v1/applicationmetadata', (req) => {
req.on('response', (res) => {
+ const body = res.body as IncomingApplicationMetadata;
if (whatToMock.appPromptForPartyOverride !== undefined) {
- res.body.promptForParty = whatToMock.appPromptForPartyOverride;
+ body.promptForParty = whatToMock.appPromptForPartyOverride;
}
if (whatToMock.partyTypesAllowed !== undefined) {
- res.body.partyTypesAllowed = whatToMock.partyTypesAllowed;
+ body.partyTypesAllowed = whatToMock.partyTypesAllowed;
+ }
+ if (whatToMock.onEntryShow !== undefined) {
+ body.onEntry = { show: whatToMock.onEntryShow };
}
});
});
}
- if (whatToMock.noActiveInstances !== false) {
- cy.intercept('**/active', []).as('noActiveInstances');
- }
+ cy.intercept('**/active', whatToMock.activeInstances || []).as('activeInstances');
}
export function removeAllButOneOrg(parties: IParty[]): IParty[] {