Skip to content

Commit

Permalink
Merge branch 'org-library-mvp' into feat/text-resource-endpoints-org-…
Browse files Browse the repository at this point in the history
…level
  • Loading branch information
Konrad-Simso committed Feb 14, 2025
2 parents d87fc56 + 3e9eb01 commit 2dfb619
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { OrgContentLibrary } from './OrgContentLibrary';
import type { RenderResult } from '@testing-library/react';
import { screen } from '@testing-library/react';
import { screen, waitFor } from '@testing-library/react';
import { textMock } from '@studio/testing/mocks/i18nMock';
import type { ProviderData } from '../../testing/mocks';
import { renderWithProviders } from '../../testing/mocks';
Expand Down Expand Up @@ -56,6 +56,24 @@ jest.mock('react-router-dom', () => jest.requireActual('react-router-dom')); //
describe('OrgContentLibrary', () => {
afterEach(jest.clearAllMocks);

it('renders a spinner when waiting for code lists', () => {
renderOrgContentLibrary({ initialEntries: [mockOrgPath] });
const spinner = screen.getByText(textMock('general.loading'));
expect(spinner).toBeInTheDocument();
});

it('Renders an error message when the code lists query fails', async () => {
const getCodeListsForOrg = () => Promise.reject(new Error('Test error'));
renderOrgContentLibrary({
queries: { getCodeListsForOrg },
queryClient: createQueryClientMock(),
initialEntries: [mockOrgPath],
});
await waitFor(expect(screen.queryByText(textMock('general.loading'))).not.toBeInTheDocument);
const errorMessage = screen.getByText(textMock('dashboard.org_library.fetch_error'));
expect(errorMessage).toBeInTheDocument();
});

it.each([SelectedContextType.None, SelectedContextType.All, SelectedContextType.Self])(
'renders alert and omits library content when context is %s',
(selectedContext) => {
Expand All @@ -73,8 +91,9 @@ describe('OrgContentLibrary', () => {
},
);

it('renders the library title', () => {
it('renders the library title', async () => {
renderOrgContentLibrary({ initialEntries: ['/some-org'] });
await waitFor(expect(screen.queryByText(textMock('general.loading'))).not.toBeInTheDocument);
const libraryTitle = screen.getByRole('heading', {
name: textMock('app_content_library.library_heading'),
});
Expand Down
38 changes: 34 additions & 4 deletions frontend/dashboard/pages/OrgContentLibrary/OrgContentLibrary.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import type { ReactElement } from 'react';
import React, { useCallback } from 'react';
import { ResourceContentLibraryImpl } from '@studio/content-library';
import type { CodeListWithMetadata } from '@studio/content-library';
import type { CodeListData, CodeListWithMetadata } from '@studio/content-library';
import { useSelectedContext } from '../../hooks/useSelectedContext';
import {
StudioAlert,
StudioCenter,
StudioParagraph,
StudioPageError,
StudioPageSpinner,
} from '@studio/components';
import { useUpdateOrgCodeListMutation } from 'app-shared/hooks/mutations/useUpdateOrgCodeListMutation';
import { useTranslation } from 'react-i18next';
import { isErrorUnknown } from 'app-shared/utils/ApiErrorUtils';
import type { ApiError } from 'app-shared/types/api/ApiError';
import { useUploadOrgCodeListMutation } from 'app-shared/hooks/mutations/useUploadOrgCodeListMutation';
import { toast } from 'react-toastify';
import type { AxiosError } from 'axios';
import { useSelectedContext } from '../../hooks/useSelectedContext';
import { useDeleteOrgCodeListMutation } from 'app-shared/hooks/mutations/useDeleteOrgCodeListMutation';
import { StudioAlert, StudioCenter, StudioParagraph } from '@studio/components';
import { isOrg } from './utils';
import { useOrgCodeListsQuery } from 'app-shared/hooks/queries/useOrgCodeListsQuery';

export function OrgContentLibrary(): ReactElement {
const selectedContext = useSelectedContext();
Expand All @@ -25,6 +32,29 @@ export function OrgContentLibrary(): ReactElement {
}

function OrgContentLibraryWithContext(): ReactElement {
const { t } = useTranslation();
const selectedContext = useSelectedContext();

const { data: codeListsResponse, status: codeListResponseStatus } =
useOrgCodeListsQuery(selectedContext);

switch (codeListResponseStatus) {
case 'pending':
return <StudioPageSpinner spinnerTitle={t('general.loading')} />;
case 'error':
return <StudioPageError message={t('dashboard.org_library.fetch_error')} />;
case 'success':
return <OrgContentLibraryWithContextAndData codeListsDataList={codeListsResponse} />;
}
}

type OrgContentLibraryWithContextAndDataProps = {
codeListsDataList: CodeListData[];
};

function OrgContentLibraryWithContextAndData({
codeListsDataList,
}: OrgContentLibraryWithContextAndDataProps): ReactElement {
const selectedContext = useSelectedContext();

const { mutate: updateOptionList } = useUpdateOrgCodeListMutation(selectedContext);
Expand All @@ -40,7 +70,7 @@ function OrgContentLibraryWithContext(): ReactElement {
pages: {
codeList: {
props: {
codeListsData: [],
codeListsData: codeListsDataList,
onDeleteCodeList: deleteCodeList,
onUpdateCodeListId: () => {},
onUpdateCodeList: handleUpdate,
Expand Down
4 changes: 2 additions & 2 deletions frontend/packages/shared/src/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
optionListReferencesPath,
userOrgPermissionsPath,
dataTypePath,
orgCodeListsPath,
} from './paths';

import type { AppReleasesResponse, DataModelMetadataResponse, SearchRepoFilterParams, SearchRepositoryResponse } from 'app-shared/types/api';
Expand Down Expand Up @@ -99,7 +100,6 @@ import type { OptionListReferences } from 'app-shared/types/OptionListReferences
import type { LayoutSetsModel } from '../types/api/dto/LayoutSetsModel';
import type { AccessPackageResource, PolicyAccessPackageAreaGroup } from 'app-shared/types/PolicyAccessPackages';
import type { DataType } from '../types/DataType';
import { codeListsResponse } from '../mocks/codeListsResponse';
import type { CodeListsResponse } from '../types/api/CodeListsResponse';
import { textResourcesMock } from '../mocks/textResourcesMock';

Expand Down Expand Up @@ -181,5 +181,5 @@ export const getProcessTaskType = (org: string, app: string, taskId: string) =>
export const fetchBelongsToGiteaOrg = () => get(belongsToOrg());

// Organisation library
export const getCodeListsForOrg = async (org: string): Promise<CodeListsResponse> => Promise.resolve(codeListsResponse); // Todo: Replace with real API call when endpoint is ready. https://github.com/Altinn/altinn-studio/issues/14505
export const getCodeListsForOrg = (org: string) => get<CodeListsResponse>(orgCodeListsPath(org));
export const getTextResourcesForOrg = async (org: string, language: string): Promise<ITextResourcesWithLanguage> => Promise.resolve(textResourcesMock); // Todo: Replace with real API call when endpoint is ready. https://github.com/Altinn/altinn-studio/issues/14503

0 comments on commit 2dfb619

Please sign in to comment.