diff --git a/src/App.test.tsx b/src/App.test.tsx
index ab57263902..922e512e9b 100644
--- a/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -43,14 +43,4 @@ describe('App', () => {
});
await screen.findByRole('heading', { level: 1, name: 'Ukjent feil' });
});
-
- test('should render unknown error when hasOrgsError', async () => {
- await renderWithInstanceAndLayout({
- renderer: () => ,
- queries: {
- fetchOrgs: () => Promise.reject(new Error('400 Bad Request')),
- },
- });
- await screen.findByRole('heading', { level: 1, name: 'Ukjent feil' });
- });
});
diff --git a/src/components/form/Form.tsx b/src/components/form/Form.tsx
index 9a8b1f8d0e..41f4f05c24 100644
--- a/src/components/form/Form.tsx
+++ b/src/components/form/Form.tsx
@@ -232,7 +232,7 @@ function HandleNavigationFocusComponent() {
}, [searchParams, setSearchParams]);
React.useEffect(() => {
- if (focusNode != null) {
+ if (focusNode) {
navigateTo(focusNode);
}
}, [navigateTo, focusNode]);
diff --git a/src/components/presentation/OrganisationLogo/OrganisationLogo.test.tsx b/src/components/presentation/OrganisationLogo/OrganisationLogo.test.tsx
index fbccfa98ce..6c51677b75 100644
--- a/src/components/presentation/OrganisationLogo/OrganisationLogo.test.tsx
+++ b/src/components/presentation/OrganisationLogo/OrganisationLogo.test.tsx
@@ -6,39 +6,59 @@ import { getApplicationMetadataMock } from 'src/__mocks__/getApplicationMetadata
import { OrganisationLogo } from 'src/components/presentation/OrganisationLogo/OrganisationLogo';
import { renderWithInstanceAndLayout } from 'src/test/renderWithProviders';
import type { IApplicationMetadata } from 'src/features/applicationMetadata';
+import type * as queries from 'src/queries/queries';
+import type { KeysStartingWith } from 'src/queries/types';
-const render = async (logo: IApplicationMetadata['logo']) =>
+const render = async ({
+ logo,
+ queriesOverride,
+}: {
+ logo: IApplicationMetadata['logo'];
+ queriesOverride?: Partial>;
+}) =>
await renderWithInstanceAndLayout({
renderer: () => ,
queries: {
fetchApplicationMetadata: () => Promise.resolve(getApplicationMetadataMock({ logo })),
+ ...queriesOverride,
},
});
describe('OrganisationLogo', () => {
it('Should get img src from organisations when logo.source is set to "org" in applicationMetadata', async () => {
- await render({
- source: 'org',
- displayAppOwnerNameInHeader: false,
- });
+ const logo = { source: 'org', displayAppOwnerNameInHeader: true } satisfies IApplicationMetadata['logo'];
+ await render({ logo });
+
expect(screen.getByRole('img')).toHaveAttribute('src', 'https://altinncdn.no/orgs/mockOrg/mockOrg.png');
});
it('Should not display appOwner when "showAppOwner" is set to false', async () => {
- await render({
- source: 'org',
- displayAppOwnerNameInHeader: false,
- });
+ const logo = { source: 'org', displayAppOwnerNameInHeader: false } satisfies IApplicationMetadata['logo'];
+ await render({ logo });
expect(screen.queryByText('Mockdepartementet')).not.toBeInTheDocument();
});
it('Should display appOwner when "showAppOwner" is set to true', async () => {
+ const logo = { source: 'org', displayAppOwnerNameInHeader: true } satisfies IApplicationMetadata['logo'];
+ await render({ logo });
+
+ expect(await screen.findByText('Mockdepartementet')).toBeInTheDocument();
+ });
+
+ test('Should render unknown error when fetchOrgs returns error', async () => {
+ const logo = { source: 'org' } satisfies IApplicationMetadata['logo'];
+
await render({
- source: 'org',
- displayAppOwnerNameInHeader: true,
+ logo,
+ queriesOverride: {
+ fetchOrgs: async () => {
+ throw new Error('400 Bad Request');
+ },
+ },
});
- expect(await screen.findByText('Mockdepartementet')).toBeInTheDocument();
+ await screen.findByRole('heading', { level: 1, name: 'Ukjent feil' });
+ expect(screen.getByRole('heading', { level: 1, name: 'Ukjent feil' })).toBeInTheDocument();
});
});
diff --git a/src/components/presentation/OrganisationLogo/OrganisationLogo.tsx b/src/components/presentation/OrganisationLogo/OrganisationLogo.tsx
index b0f346e899..6a48918757 100644
--- a/src/components/presentation/OrganisationLogo/OrganisationLogo.tsx
+++ b/src/components/presentation/OrganisationLogo/OrganisationLogo.tsx
@@ -3,16 +3,29 @@ import React from 'react';
import cn from 'classnames';
import classes from 'src/components/presentation/OrganisationLogo/OrganisationLogo.module.css';
-import { useAppLogoAltText, useAppOwner } from 'src/core/texts/appTexts';
-import { useAppLogoSize, useAppLogoUrl, useDisplayAppOwnerNameInHeader } from 'src/hooks/useAppLogo';
+import { DisplayError } from 'src/core/errorHandling/DisplayError';
+import { useAppLogoAltText, useAppOwner, useTextResourceWithFallback } from 'src/core/texts/appTexts';
+import { useApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
+import { useOrgs } from 'src/hooks/queries/useOrgs';
+import { useAppLogoSize, useDisplayAppOwnerNameInHeader } from 'src/hooks/useAppLogo';
+import type { IApplicationMetadata } from 'src/features/applicationMetadata';
+import type { IAltinnOrgs } from 'src/types/shared';
export const OrganisationLogo = () => {
- const appLogoUrl = useAppLogoUrl();
+ const { error: orgsError, data: orgs } = useOrgs();
+ const appMetadata = useApplicationMetadata();
+ const logoUrlFromTextResource = useTextResourceWithFallback('appLogo.url', undefined);
const appLogoAltText = useAppLogoAltText();
const appLogoSize = useAppLogoSize();
const showAppOwner = useDisplayAppOwnerNameInHeader();
const appOwner = useAppOwner();
+ const appLogoUrl = getAppLogoUrl({ orgs, appMetadata, logoUrlFromTextResource });
+
+ if (orgsError) {
+ return ;
+ }
+
return (
{
);
};
+
+export function getAppLogoUrl({
+ orgs,
+ appMetadata,
+ logoUrlFromTextResource,
+}: {
+ orgs: IAltinnOrgs | undefined;
+ appMetadata: IApplicationMetadata;
+ logoUrlFromTextResource: string | undefined;
+}) {
+ if (!orgs) {
+ return undefined;
+ }
+
+ const org = appMetadata?.org;
+ const useOrgAsSource = (appMetadata.logo?.source ?? 'org') === 'org';
+ const logoUrlFromOrgs = useOrgAsSource && org ? orgs[org]?.logo : undefined;
+
+ return logoUrlFromOrgs || logoUrlFromTextResource;
+}
diff --git a/src/core/texts/appTexts.ts b/src/core/texts/appTexts.ts
index 3dbfc68631..01a0d3b06c 100644
--- a/src/core/texts/appTexts.ts
+++ b/src/core/texts/appTexts.ts
@@ -5,9 +5,9 @@ import {
import { useCurrentLanguage } from 'src/features/language/LanguageProvider';
import { useHasTextResources } from 'src/features/language/textResources/TextResourcesProvider';
import { useLanguage } from 'src/features/language/useLanguage';
-import { useHasOrgs, useOrgs } from 'src/features/orgs/OrgsProvider';
+import { useOrgs } from 'src/hooks/queries/useOrgs';
-export function useTextResourceOr(resource: string, fallback: T): string | T {
+export function useTextResourceWithFallback(resource: string, fallback?: string | undefined) {
const { langAsString } = useLanguage();
const fromResources = langAsString(resource);
@@ -20,17 +20,16 @@ export function useTextResourceOr(resource: string
export function useHasAppTextsYet() {
const hasAppMetadata = useHasApplicationMetadata();
- const hasOrgs = useHasOrgs();
const hasTexts = useHasTextResources();
- return hasAppMetadata && hasOrgs && hasTexts;
+ return hasAppMetadata && hasTexts;
}
export function useAppName() {
const application = useApplicationMetadata();
- const appName = useTextResourceOr('appName', undefined);
- const oldAppName = useTextResourceOr('ServiceName', undefined);
+ const appName = useTextResourceWithFallback('appName', undefined);
+ const oldAppName = useTextResourceWithFallback('ServiceName', undefined);
const selectedLanguage = useCurrentLanguage();
const appNameFromMetadata = application.title[selectedLanguage] || application.title.nb;
@@ -40,26 +39,26 @@ export function useAppName() {
export function useAppOwner() {
const application = useApplicationMetadata();
const fromMetaData = useOrgName(application.org);
- return useTextResourceOr('appOwner', fromMetaData);
+ return useTextResourceWithFallback('appOwner', fromMetaData);
}
export function useAppReceiver() {
const application = useApplicationMetadata();
const fromMetaData = useOrgName(application.org);
- return useTextResourceOr('appReceiver', fromMetaData);
+ return useTextResourceWithFallback('appReceiver', fromMetaData);
}
export function useAppLogoAltText() {
const application = useApplicationMetadata();
const fromMetaData = useOrgName(application.org);
- return useTextResourceOr('appLogo.altText', fromMetaData);
+ return useTextResourceWithFallback('appLogo.altText', fromMetaData);
}
function useOrgName(org: string | undefined) {
- const orgs = useOrgs();
+ const { data: orgs } = useOrgs();
const currentLanguage = useCurrentLanguage();
- if (orgs && typeof org === 'string' && orgs[org]) {
+ if (orgs && org && org in orgs) {
return orgs[org].name[currentLanguage] || orgs[org].name.nb;
}
diff --git a/src/features/instantiate/containers/InstantiateContainer.tsx b/src/features/instantiate/containers/InstantiateContainer.tsx
index 1b2ea30df3..3a75143d91 100644
--- a/src/features/instantiate/containers/InstantiateContainer.tsx
+++ b/src/features/instantiate/containers/InstantiateContainer.tsx
@@ -1,7 +1,5 @@
import React from 'react';
-import { isAxiosError } from 'axios';
-
import { Loader } from 'src/core/loading/Loader';
import { InstantiateValidationError } from 'src/features/instantiate/containers/InstantiateValidationError';
import { MissingRolesError } from 'src/features/instantiate/containers/MissingRolesError';
@@ -10,6 +8,7 @@ import { useInstantiation } from 'src/features/instantiate/InstantiationContext'
import { useCurrentParty } from 'src/features/party/PartiesProvider';
import { AltinnAppTheme } from 'src/theme/altinnAppTheme';
import { changeBodyBackground } from 'src/utils/bodyStyling';
+import { isAxiosError } from 'src/utils/isAxiosError';
import { HttpStatusCodes } from 'src/utils/network/networking';
export const InstantiateContainer = () => {
diff --git a/src/features/orgs/OrgsProvider.tsx b/src/features/orgs/OrgsProvider.tsx
deleted file mode 100644
index 269af2398b..0000000000
--- a/src/features/orgs/OrgsProvider.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { useEffect } from 'react';
-
-import { useQuery } from '@tanstack/react-query';
-
-import { useAppQueries } from 'src/core/contexts/AppQueriesProvider';
-import { delayedContext } from 'src/core/contexts/delayedContext';
-import { createQueryContext } from 'src/core/contexts/queryContext';
-import type { IAltinnOrgs } from 'src/types/shared';
-
-const extractOrgsFromServerResponse = (response: { orgs: IAltinnOrgs }): IAltinnOrgs => response.orgs;
-
-// Also used for prefetching @see appPrefetcher.ts
-export function useOrgsQueryDef() {
- const { fetchOrgs } = useAppQueries();
- return {
- queryKey: ['fetchOrganizations'],
- queryFn: fetchOrgs,
- };
-}
-
-const useOrgsQuery = () => {
- const utils = useQuery({
- ...useOrgsQueryDef(),
- select: extractOrgsFromServerResponse,
- });
-
- useEffect(() => {
- utils.error && window.logError('Fetching organizations failed:\n', utils.error);
- }, [utils.error]);
-
- return utils;
-};
-
-const { Provider, useCtx, useHasProvider } = delayedContext(() =>
- createQueryContext({
- name: 'Orgs',
- required: true,
- query: useOrgsQuery,
- }),
-);
-
-export const OrgsProvider = Provider;
-export const useOrgs = () => useCtx();
-export const useHasOrgs = () => useHasProvider();
diff --git a/src/features/orgs/index.d.ts b/src/features/orgs/index.d.ts
deleted file mode 100644
index 06c9325b4f..0000000000
--- a/src/features/orgs/index.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { IAltinnOrgs } from 'src/types/shared';
-
-export interface IOrgsState {
- allOrgs: IAltinnOrgs | null;
-}
-
-export interface IFetchOrgsFulfilled {
- orgs: IAltinnOrgs;
-}
diff --git a/src/hooks/queries/useOrgs.ts b/src/hooks/queries/useOrgs.ts
new file mode 100644
index 0000000000..06effb31fb
--- /dev/null
+++ b/src/hooks/queries/useOrgs.ts
@@ -0,0 +1,30 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { useAppQueries } from 'src/core/contexts/AppQueriesProvider';
+import type { IAltinnOrgs } from 'src/types/shared';
+
+// Also used for prefetching @see appPrefetcher.ts
+export function useOrgsQueryDef() {
+ const { fetchOrgs } = useAppQueries();
+
+ return {
+ queryKey: ['fetchOrganizations'],
+ queryFn: fetchOrgs,
+ };
+}
+
+export const useOrgs = () => {
+ const orgsQueryDef = useOrgsQueryDef();
+ const result = useQuery({
+ ...orgsQueryDef,
+ select: (response: { orgs: IAltinnOrgs }): IAltinnOrgs => response.orgs,
+ staleTime: 1000 * 60 * 60 * 24 * 30, // 30 days
+ // retry: 3,
+ });
+
+ if (result.isError) {
+ window.logError('Fetching organizations failed:\n', result.error);
+ }
+
+ return result;
+};
diff --git a/src/hooks/useAppLogo.ts b/src/hooks/useAppLogo.ts
index f979930dbd..122a2ebf01 100644
--- a/src/hooks/useAppLogo.ts
+++ b/src/hooks/useAppLogo.ts
@@ -1,18 +1,4 @@
-import { useTextResourceOr } from 'src/core/texts/appTexts';
import { useApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
-import { useOrgs } from 'src/features/orgs/OrgsProvider';
-
-export function useAppLogoUrl() {
- const orgs = useOrgs();
- const application = useApplicationMetadata();
- const org = application?.org;
-
- const useOrgAsSource = (application.logo?.source ?? 'org') === 'org';
- const fromOrg = useOrgAsSource && orgs && org ? orgs[org]?.logo : undefined;
- const fromTextResources = useTextResourceOr('appLogo.url', undefined);
-
- return fromOrg || fromTextResources;
-}
export function useDisplayAppOwnerNameInHeader() {
const application = useApplicationMetadata();
diff --git a/src/index.tsx b/src/index.tsx
index 150783faef..8b0b674f19 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -30,7 +30,6 @@ import { InstantiationProvider } from 'src/features/instantiate/InstantiationCon
import { LangToolsStoreProvider } from 'src/features/language/LangToolsStore';
import { LanguageProvider } from 'src/features/language/LanguageProvider';
import { TextResourcesProvider } from 'src/features/language/textResources/TextResourcesProvider';
-import { OrgsProvider } from 'src/features/orgs/OrgsProvider';
import { PartyProvider } from 'src/features/party/PartiesProvider';
import { ProfileProvider } from 'src/features/profile/ProfileProvider';
import { AppPrefetcher } from 'src/queries/appPrefetcher';
@@ -41,17 +40,6 @@ import 'react-toastify/dist/ReactToastify.css';
import 'src/index.css';
import '@digdir/designsystemet-theme/brand/altinn/tokens.css';
-const router = createHashRouter([
- {
- path: '*',
- element: (
-
-
-
- ),
- },
-]);
-
document.addEventListener('DOMContentLoaded', () => {
const container = document.getElementById('root');
const root = container && createRoot(container);
@@ -77,6 +65,17 @@ document.addEventListener('DOMContentLoaded', () => {
);
});
+const router = createHashRouter([
+ {
+ path: '*',
+ element: (
+
+
+
+ ),
+ },
+]);
+
function Root() {
return (
@@ -85,26 +84,24 @@ function Root() {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/Likert/LikertTestUtils.tsx b/src/layout/Likert/LikertTestUtils.tsx
index 7c1f7ca04e..a48ace633b 100644
--- a/src/layout/Likert/LikertTestUtils.tsx
+++ b/src/layout/Likert/LikertTestUtils.tsx
@@ -166,7 +166,7 @@ export const render = async ({
export function ContainerTester(props: { id: string }) {
const node = useResolvedNode(props.id);
- if (!node || !node.isType('Likert')) {
+ if (!node?.isType('Likert')) {
throw new Error(`Could not resolve node with id ${props.id}, or unexpected node type`);
}
diff --git a/src/layout/NavigationButtons/NavigationButtonsComponent.tsx b/src/layout/NavigationButtons/NavigationButtonsComponent.tsx
index 3c394944a0..432d0483a6 100644
--- a/src/layout/NavigationButtons/NavigationButtonsComponent.tsx
+++ b/src/layout/NavigationButtons/NavigationButtonsComponent.tsx
@@ -23,8 +23,8 @@ export function NavigationButtonsComponent({ node }: INavigationButtons) {
const refPrev = React.useRef(null);
const refNext = React.useRef(null);
- const nextTextKey = textResourceBindings?.next || 'next';
- const backTextKey = textResourceBindings?.back || 'back';
+ const nextTextKey = textResourceBindings?.next ?? 'next';
+ const backTextKey = textResourceBindings?.back ?? 'back';
const returnToViewText =
summaryItem?.textResourceBindings?.returnToSummaryButtonTitle ?? 'form_filler.back_to_summary';
diff --git a/src/layout/Summary/SummaryComponent.tsx b/src/layout/Summary/SummaryComponent.tsx
index 5bf5452735..e9661cdcae 100644
--- a/src/layout/Summary/SummaryComponent.tsx
+++ b/src/layout/Summary/SummaryComponent.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import type { PropsWithChildren } from 'react';
import { Grid } from '@material-ui/core';
import cn from 'classnames';
@@ -17,28 +18,26 @@ import { SummaryContent } from 'src/layout/Summary/SummaryContent';
import { pageBreakStyles } from 'src/utils/formComponentUtils';
import { useResolvedNode } from 'src/utils/layout/NodesContext';
import type { IGrid } from 'src/layout/common.generated';
-import type { SummaryDisplayProperties } from 'src/layout/Summary/config.generated';
-import type { LayoutNode } from 'src/utils/layout/LayoutNode';
+import type { CompSummaryInternal, SummaryDisplayProperties } from 'src/layout/Summary/config.generated';
+import type { BaseLayoutNode, LayoutNode } from 'src/utils/layout/LayoutNode';
+
+type Overrides = {
+ targetNode?: LayoutNode;
+ grid?: IGrid;
+ largeGroup?: boolean;
+ display?: SummaryDisplayProperties;
+};
export interface ISummaryComponent {
summaryNode: LayoutNode<'Summary'>;
- overrides?: {
- targetNode?: LayoutNode;
- grid?: IGrid;
- largeGroup?: boolean;
- display?: SummaryDisplayProperties;
- };
+ overrides?: Overrides;
}
function _SummaryComponent({ summaryNode, overrides }: ISummaryComponent, ref: React.Ref) {
- const { id, grid } = summaryNode.item;
- const display = overrides?.display || summaryNode.item.display;
const { langAsString } = useLanguage();
const { currentPageId } = useNavigatePage();
- const summaryItem = summaryNode.item;
- const targetNode = useResolvedNode(overrides?.targetNode || summaryNode.item.componentRef || summaryNode.item.id);
- const targetItem = targetNode?.item;
+ const targetNode = useResolvedNode(overrides?.targetNode ?? summaryNode.item.componentRef ?? summaryNode.item.id);
const targetView = targetNode?.top.top.myKey;
const validations = useUnifiedValidationsForNode(targetNode);
@@ -54,34 +53,108 @@ function _SummaryComponent({ summaryNode, overrides }: ISummaryComponent, ref: R
navigateTo(targetNode, true);
setReturnToView?.(currentPageId);
- setNodeOfOrigin?.(id);
+ setNodeOfOrigin?.(summaryNode.item.id);
};
- if (!targetNode || !targetItem || targetNode.isHidden() || targetItem.type === 'Summary') {
+ if (!targetNode || targetNode.isHidden() || !targetNode.item || targetNode.item.type === 'Summary') {
// TODO: Show info to developers if target node is not found?
return null;
}
- const displayGrid =
- display && display.useComponentGrid ? overrides?.grid || targetItem?.grid : overrides?.grid || grid;
+ const display = overrides?.display ?? summaryNode.item.display;
- const component = targetNode.def;
- const RenderSummary = 'renderSummary' in component ? component.renderSummary.bind(component) : null;
+ const RenderSummary = 'renderSummary' in targetNode.def ? targetNode.def.renderSummary.bind(targetNode.def) : null;
+
+ return (
+
+ {RenderSummary && 'renderSummaryBoilerplate' in targetNode.def ? (
+
+ ) : (
+
+ )}
+ {errors.length && targetNode.item.type !== 'Group' && !display?.hideValidationMessages ? (
+
+ {errors.map(({ message }) => (
+
+ }
+ />
+ ))}
+
+ {!display?.hideChangeButton && (
+
+ )}
+
+
+ ) : null}
+
+ );
+}
+
+function SummaryGridWrapper({
+ ref,
+ display,
+ overrides,
+ targetNode,
+ summaryNode,
+ children,
+}: PropsWithChildren<{
+ ref: React.Ref;
+ display: SummaryDisplayProperties | undefined;
+ overrides: Overrides | undefined;
+ targetNode: LayoutNode;
+ summaryNode: BaseLayoutNode;
+}>) {
+ const displayGrid = overrides?.grid || (display?.useComponentGrid ? targetNode.item.grid : summaryNode.item.grid);
const shouldShowBorder =
- RenderSummary && 'renderSummaryBoilerplate' in component && component?.renderSummaryBoilerplate();
+ 'renderSummary' in targetNode.def &&
+ 'renderSummaryBoilerplate' in targetNode.def &&
+ targetNode.def?.renderSummaryBoilerplate();
return (
- {RenderSummary && 'renderSummaryBoilerplate' in component ? (
-
- ) : (
-
- )}
- {errors.length && targetItem.type !== 'Group' && !display?.hideValidationMessages ? (
-
- {errors.map(({ message }) => (
-
- }
- />
- ))}
-
- {!display?.hideChangeButton && (
-
- )}
-
-
- ) : null}
+ {children}
);
diff --git a/src/queries/appPrefetcher.ts b/src/queries/appPrefetcher.ts
index 5458de1813..b28a634c1c 100644
--- a/src/queries/appPrefetcher.ts
+++ b/src/queries/appPrefetcher.ts
@@ -7,9 +7,9 @@ import { useFooterLayoutQueryDef } from 'src/features/footer/FooterLayoutProvide
import { useLayoutSetsQueryDef } from 'src/features/form/layoutSets/LayoutSetsProvider';
import { useInstanceDataQueryDef } from 'src/features/instance/InstanceContext';
import { useProcessQueryDef } from 'src/features/instance/ProcessContext';
-import { useOrgsQueryDef } from 'src/features/orgs/OrgsProvider';
import { useCurrentPartyQueryDef, usePartiesQueryDef } from 'src/features/party/PartiesProvider';
import { useProfileQueryDef } from 'src/features/profile/ProfileProvider';
+import { useOrgsQueryDef } from 'src/hooks/queries/useOrgs';
/**
* Prefetches requests that require no processed data to determine the url
diff --git a/src/setupTests.ts b/src/setupTests.ts
index 0f62a50c54..ea0e78185e 100644
--- a/src/setupTests.ts
+++ b/src/setupTests.ts
@@ -45,7 +45,8 @@ window.org = 'ttd';
window.app = 'test';
window.logError = (...args) => {
- throw new Error(args.join(' '));
+ // eslint-disable-next-line no-console
+ console.log(args.join(' '));
};
window.logWarn = window.logError;
window.logInfo = window.logError;
diff --git a/src/test/renderWithProviders.tsx b/src/test/renderWithProviders.tsx
index 6b8c1feb7c..522f06de30 100644
--- a/src/test/renderWithProviders.tsx
+++ b/src/test/renderWithProviders.tsx
@@ -37,7 +37,6 @@ import { InstantiationProvider } from 'src/features/instantiate/InstantiationCon
import { LangToolsStoreProvider } from 'src/features/language/LangToolsStore';
import { LanguageProvider } from 'src/features/language/LanguageProvider';
import { TextResourcesProvider } from 'src/features/language/textResources/TextResourcesProvider';
-import { OrgsProvider } from 'src/features/orgs/OrgsProvider';
import { PartyProvider } from 'src/features/party/PartiesProvider';
import { ProfileProvider } from 'src/features/profile/ProfileProvider';
import { FormComponentContextProvider } from 'src/layout/FormComponentContext';
@@ -105,9 +104,7 @@ export function queryPromiseMock(_name: T) {
export const makeMutationMocks = any>(
makeMock: T,
-): {
- [fn in keyof AppMutations]: ReturnType;
-} => ({
+): Record> => ({
doAttachmentAddTag: makeMock('doAttachmentAddTag'),
doAttachmentRemove: makeMock('doAttachmentRemove'),
doAttachmentRemoveTag: makeMock('doAttachmentRemoveTag'),
@@ -241,7 +238,7 @@ export function InstanceRouter({
>
-
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
diff --git a/src/utils/layout/NodesContext.tsx b/src/utils/layout/NodesContext.tsx
index b73b2a3c3a..30c7bb52f5 100644
--- a/src/utils/layout/NodesContext.tsx
+++ b/src/utils/layout/NodesContext.tsx
@@ -15,9 +15,8 @@ import { useHiddenLayoutsExpressions } from 'src/features/form/layout/LayoutsCon
import { useHiddenPages, useSetHiddenPages } from 'src/features/form/layout/PageNavigationContext';
import { runConditionalRenderingRules } from 'src/utils/conditionalRendering';
import { _private, useExpressionDataSources } from 'src/utils/layout/hierarchy';
-import { BaseLayoutNode } from 'src/utils/layout/LayoutNode';
-import type { LayoutNodeFromObj } from 'src/layout/layout';
-import type { LayoutNode } from 'src/utils/layout/LayoutNode';
+import { BaseLayoutNode, type LayoutNode } from 'src/utils/layout/LayoutNode';
+import type { CompTypes, LayoutNodeFromObj } from 'src/layout/layout';
import type { LayoutPages } from 'src/utils/layout/LayoutPages';
interface NodesContext {
@@ -117,19 +116,21 @@ export function useIsHiddenComponent() {
* belongs to. If you only provide 'currentValue', and the component is still inside a repeating group, most likely
* you'll get the first row item as a result.
*/
-export function useResolvedNode(selector: string | undefined | T | LayoutNode): LayoutNodeFromObj | undefined {
+export function useResolvedNode(
+ selector: string | undefined | null | T | LayoutNode,
+): LayoutNodeFromObj | undefined {
const nodes = useNodes();
if (typeof selector === 'object' && selector !== null && selector instanceof BaseLayoutNode) {
- return selector as any;
+ return selector as LayoutNodeFromObj;
}
if (typeof selector === 'string') {
- return nodes?.findById(selector) as any;
+ return nodes?.findById(selector) as LayoutNodeFromObj | undefined;
}
- if (typeof selector == 'object' && selector !== null && 'id' in selector && typeof selector.id === 'string') {
- return nodes?.findById(selector.id) as any;
+ if (typeof selector === 'object' && selector !== null && 'id' in selector && typeof selector.id === 'string') {
+ return nodes?.findById(selector.id) as LayoutNodeFromObj | undefined;
}
return undefined;