Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removes OrgsProvider in favor of hook #2124

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: () => <App />,
queries: {
fetchOrgs: () => Promise.reject(new Error('400 Bad Request')),
},
});
await screen.findByRole('heading', { level: 1, name: 'Ukjent feil' });
});
});
2 changes: 1 addition & 1 deletion src/components/form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ function HandleNavigationFocusComponent() {
}, [searchParams, setSearchParams]);

React.useEffect(() => {
if (focusNode != null) {
if (focusNode) {
navigateTo(focusNode);
}
}, [navigateTo, focusNode]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<KeysStartingWith<typeof queries, 'fetch'>>;
}) =>
await renderWithInstanceAndLayout({
renderer: () => <OrganisationLogo />,
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();
});
});
39 changes: 36 additions & 3 deletions src/components/presentation/OrganisationLogo/OrganisationLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <DisplayError error={orgsError} />;
}

return (
<div className={classes.container}>
<img
Expand All @@ -24,3 +37,23 @@ export const OrganisationLogo = () => {
</div>
);
};

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;
}
21 changes: 10 additions & 11 deletions src/core/texts/appTexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends string | undefined>(resource: string, fallback: T): string | T {
export function useTextResourceWithFallback(resource: string, fallback?: string | undefined) {
const { langAsString } = useLanguage();

const fromResources = langAsString(resource);
Expand All @@ -20,17 +20,16 @@ export function useTextResourceOr<T extends string | undefined>(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;

Expand All @@ -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;
}

Expand Down
3 changes: 1 addition & 2 deletions src/features/instantiate/containers/InstantiateContainer.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 = () => {
Expand Down
44 changes: 0 additions & 44 deletions src/features/orgs/OrgsProvider.tsx

This file was deleted.

9 changes: 0 additions & 9 deletions src/features/orgs/index.d.ts

This file was deleted.

30 changes: 30 additions & 0 deletions src/hooks/queries/useOrgs.ts
Original file line number Diff line number Diff line change
@@ -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;
};
14 changes: 0 additions & 14 deletions src/hooks/useAppLogo.ts
Original file line number Diff line number Diff line change
@@ -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();
Expand Down
Loading
Loading