Skip to content

Commit c62f6e6

Browse files
hofermoNilsXitaso
andauthored
feat(aas-list): Show Registry Entries (#488)
* feat: add support for AAS registries in AasListDataWrapper and related components * feat: enhance value extraction for manufacturer details in getNameplateValuesForAAS * fix: add optional chaining to prevent potential runtime errors in getNameplateValuesForAAS * feat: update repository dropdown labels to include AAS Registry for improved clarity * feat: add connectionType prop to AasList and related components for improved data handling * fix: refine value extraction logic in extractValue function for improved handling of API responses * Fix wrong loading of Registry Descriptors * linting * Fix tests * Add debug configuration for JEST Unit tests * Add comment regarding the JSON handling in API Response Wrapper * Rename SelectRepository in SelectListSource --------- Co-authored-by: Nils Rothamel <nils.rothamel@xitaso.com>
1 parent dbf6188 commit c62f6e6

20 files changed

+459
-132
lines changed

.vscode/launch.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@
4545
"sourceMapPathOverrides": {
4646
"/turbopack/[project]/*": "${webRoot}/*"
4747
}
48+
},
49+
{
50+
"name": "Debug Jest file",
51+
"type": "node",
52+
"request": "launch",
53+
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/jest",
54+
"args": ["${fileBasenameNoExtension}", "--runInBand", "--watch", "--coverage=false", "--no-cache"],
55+
"cwd": "${workspaceRoot}",
56+
"console": "integratedTerminal",
57+
"internalConsoleOptions": "neverOpen",
58+
"sourceMaps": true,
59+
"windows": {
60+
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
61+
}
4862
}
4963
]
5064
}

src/app/[locale]/list/_components/AasList.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ import { RepositoryWithInfrastructure } from 'lib/services/database/Infrastructu
77

88
type AasListProps = {
99
repositoryUrl: RepositoryWithInfrastructure;
10+
connectionType?: 'repository' | 'registry';
1011
shells: AasListDto | undefined;
1112
comparisonFeatureFlag?: boolean;
1213
selectedAasList: string[] | undefined;
1314
updateSelectedAasList: (isChecked: boolean, aasId: string | undefined) => void;
1415
};
1516

1617
export default function AasList(props: AasListProps) {
17-
const { repositoryUrl, shells, selectedAasList, updateSelectedAasList, comparisonFeatureFlag } = props;
18+
const { repositoryUrl, connectionType, shells, selectedAasList, updateSelectedAasList, comparisonFeatureFlag } =
19+
props;
1820
const t = useTranslations('pages.aasList');
1921
const MAX_SELECTED_ITEMS = 3;
2022

@@ -76,6 +78,7 @@ export default function AasList(props: AasListProps) {
7678
<TableRow key={aasListEntry.aasId} data-testid={`list-row-${aasListEntry.aasId}`}>
7779
<AasListTableRow
7880
repository={repositoryUrl}
81+
connectionType={connectionType}
7982
aasListEntry={aasListEntry}
8083
comparisonFeatureFlag={comparisonFeatureFlag}
8184
checkBoxDisabled={checkBoxDisabled}

src/app/[locale]/list/_components/AasListDataWrapper.spec.tsx

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ListEntityDto } from 'lib/services/list-service/ListService';
99
import { Internationalization } from 'lib/i18n/Internationalization';
1010
import { AasStoreProvider } from 'stores/AasStore';
1111
import { RepositoryWithInfrastructure } from 'lib/services/database/InfrastructureMappedTypes';
12+
import { ConnectionWithType } from 'app/[locale]/list/_components/filter/SelectListSource';
1213

1314
jest.mock('./../../../../lib/services/list-service/aasListApiActions');
1415
jest.mock('./../../../../lib/services/database/infrastructureDatabaseActions');
@@ -35,6 +36,12 @@ jest.mock('next-auth', jest.fn());
3536
const REPOSITORY_URL = 'https://test-repository.de';
3637
const FIRST_PAGE_CURSOR = '123123';
3738
const REPOSITORY = { url: REPOSITORY_URL, infrastructureName: 'Test Infrastructure', id: 'test-repo-id' };
39+
const REPOSITORY_CONNECTION_TYPE = {
40+
url: REPOSITORY.url,
41+
infrastructureName: REPOSITORY.infrastructureName,
42+
id: REPOSITORY.id,
43+
type: 'repository',
44+
};
3845
const mockDB = jest.fn(() => {
3946
return [REPOSITORY];
4047
});
@@ -56,7 +63,12 @@ const createTestListEntries = (from = 0, to = 10): ListEntityDto[] => {
5663
};
5764

5865
const mockActionFirstPage = jest.fn(
59-
(_repository: RepositoryWithInfrastructure, _count: number, _cursor: string | undefined) => {
66+
(
67+
_repository: RepositoryWithInfrastructure | ConnectionWithType,
68+
_count: number,
69+
_cursor: string | undefined,
70+
_type: string | undefined,
71+
) => {
6072
return {
6173
success: true,
6274
entities: createTestListEntries(0, 10),
@@ -67,7 +79,12 @@ const mockActionFirstPage = jest.fn(
6779
);
6880

6981
const mockActionSecondPage = jest.fn(
70-
(_repository: RepositoryWithInfrastructure, _count: number, _cursor: string | undefined) => {
82+
(
83+
_repository: RepositoryWithInfrastructure,
84+
_count: number,
85+
_cursor: string | undefined,
86+
_type: string | undefined,
87+
) => {
7188
return {
7289
success: true,
7390
entities: createTestListEntries(10, 12),
@@ -90,6 +107,11 @@ describe('AASListDataWrapper', () => {
90107
(serverActions.getAasListEntities as jest.Mock).mockImplementation(mockActionFirstPage);
91108

92109
(connectionServerActions.getAasRepositoriesIncludingDefault as jest.Mock).mockImplementation(mockDB);
110+
(connectionServerActions.getAasRegistriesIncludingDefault as jest.Mock).mockImplementation(
111+
jest.fn(() => {
112+
return [];
113+
}),
114+
);
93115
(nameplateDataActions.getNameplateValuesForAAS as jest.Mock).mockImplementation(mockNameplateData);
94116

95117
CustomRender(
@@ -109,7 +131,8 @@ describe('AASListDataWrapper', () => {
109131
await waitFor(() => screen.getByTestId('repository-select'));
110132
const select = screen.getAllByRole('combobox')[0];
111133
fireEvent.mouseDown(select);
112-
const firstElement = screen.getAllByRole('option')[0];
134+
// const firstElement = screen.getAllByRole('option')[0];
135+
const firstElement = screen.getByTestId('repository-select-item-0');
113136
fireEvent.click(firstElement);
114137

115138
await waitFor(() => screen.getByTestId('list-next-button'));
@@ -130,7 +153,12 @@ describe('AASListDataWrapper', () => {
130153
expect(screen.getByText('assetId10', { exact: false })).toBeInTheDocument();
131154
expect(screen.getByText('Page 2', { exact: false })).toBeInTheDocument();
132155
expect(screen.getByTestId('list-next-button')).toBeDisabled();
133-
expect(mockActionSecondPage).toHaveBeenCalledWith(REPOSITORY, 10, FIRST_PAGE_CURSOR);
156+
expect(mockActionSecondPage).toHaveBeenCalledWith(
157+
REPOSITORY_CONNECTION_TYPE,
158+
10,
159+
FIRST_PAGE_CURSOR,
160+
'repository',
161+
);
134162
});
135163

136164
it('Navigates one page back when clicking on the back button', async () => {
@@ -146,7 +174,7 @@ describe('AASListDataWrapper', () => {
146174

147175
expect(screen.getByText('assetId3', { exact: false })).toBeInTheDocument();
148176
expect(screen.getByText('Page 1', { exact: false })).toBeInTheDocument();
149-
expect(mockActionFirstPage).toHaveBeenCalledWith(REPOSITORY, 10, undefined);
177+
expect(mockActionFirstPage).toHaveBeenCalledWith(REPOSITORY_CONNECTION_TYPE, 10, undefined, 'repository');
150178
});
151179
});
152180
});

src/app/[locale]/list/_components/AasListDataWrapper.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { AasListComparisonHeader } from './AasListComparisonHeader';
1010
import { Box, Card, CardContent, IconButton, Typography } from '@mui/material';
1111
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
1212
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
13-
import { SelectRepository } from './filter/SelectRepository';
13+
import { SelectListSource } from './filter/SelectListSource';
1414
import { useTranslations } from 'next-intl';
1515
import { ApiResponseWrapperError } from 'lib/util/apiResponseWrapper/apiResponseWrapper';
1616
import { AuthenticationPrompt } from 'components/authentication/AuthenticationPrompt';
@@ -28,6 +28,7 @@ export default function AasListDataWrapper({ hideRepoSelection }: AasListDataWra
2828
const [, setAasListFiltered] = useState<ListEntityDto[]>();
2929
const [selectedAasList, setSelectedAasList] = useState<string[]>();
3030
const [selectedRepository, setSelectedRepository] = useState<RepositoryWithInfrastructure | null | undefined>();
31+
const [selectedType, setSelectedType] = useState<'repository' | 'registry' | undefined>();
3132
const env = useEnv();
3233
const t = useTranslations('pages.aasList');
3334
const { showError } = useShowError();
@@ -56,7 +57,7 @@ export default function AasListDataWrapper({ hideRepoSelection }: AasListDataWra
5657

5758
setIsLoadingList(true);
5859
clearResults();
59-
const response = await getAasListEntities(selectedRepository, 10, newCursor);
60+
const response = await getAasListEntities(selectedRepository, 10, newCursor, selectedType);
6061

6162
if (response.success) {
6263
setAasList(response);
@@ -136,7 +137,7 @@ export default function AasListDataWrapper({ hideRepoSelection }: AasListDataWra
136137
if (!selectedRepository) {
137138
return (
138139
<Box>
139-
<Typography data-testid="select-repository-text">{t('selectRepository')}</Typography>
140+
<Typography data-testid="select-repository-text">{t('selectListSource')}</Typography>
140141
</Box>
141142
);
142143
}
@@ -150,6 +151,7 @@ export default function AasListDataWrapper({ hideRepoSelection }: AasListDataWra
150151
<AasList
151152
data-testid="aas-list"
152153
repositoryUrl={selectedRepository}
154+
connectionType={selectedType}
153155
shells={aasList}
154156
selectedAasList={selectedAasList}
155157
updateSelectedAasList={updateSelectedAasList}
@@ -166,7 +168,10 @@ export default function AasListDataWrapper({ hideRepoSelection }: AasListDataWra
166168
{!hideRepoSelection && (
167169
<Box display="flex" justifyContent="space-between" marginBottom="1.625rem" paddingX="1rem">
168170
<Box display="flex" gap={4}>
169-
<SelectRepository onSelectedRepositoryChanged={setSelectedRepository} />
171+
<SelectListSource
172+
onSelectedRepositoryChanged={setSelectedRepository}
173+
onSelectedTypeChanged={setSelectedType}
174+
/>
170175
</Box>
171176
{env.COMPARISON_FEATURE_FLAG && (
172177
<AasListComparisonHeader

src/app/[locale]/list/_components/AasListTableRow.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { RepositoryWithInfrastructure } from 'lib/services/database/Infrastructu
2121

2222
type AasTableRowProps = {
2323
repository: RepositoryWithInfrastructure;
24+
connectionType?: 'repository' | 'registry';
2425
aasListEntry: ListEntityDto;
2526
comparisonFeatureFlag: boolean | undefined;
2627
checkBoxDisabled: (aasId: string | undefined) => boolean | undefined;
@@ -37,6 +38,7 @@ const tableBodyText = {
3738
export const AasListTableRow = (props: AasTableRowProps) => {
3839
const {
3940
repository,
41+
connectionType,
4042
aasListEntry,
4143
comparisonFeatureFlag,
4244
checkBoxDisabled,
@@ -66,9 +68,10 @@ export const AasListTableRow = (props: AasTableRowProps) => {
6668
const baseUrl = window.location.origin;
6769
const pageToGo = env.PRODUCT_VIEW_FEATURE_FLAG ? '/product' : '/viewer';
6870

69-
const repoUrlParam = repository.url ? `?repoUrl=${repository.url}` : '';
71+
// Only send repoUrl parameter if it's a repository, not a registry
72+
const repoUrlParam = connectionType === 'repository' && repository.url ? `?repoUrl=${repository.url}` : '';
7073
const infrastructureParam = repository.infrastructureName
71-
? `&infrastructure=${repository.infrastructureName}`
74+
? `${repoUrlParam ? '&' : '?'}infrastructure=${repository.infrastructureName}`
7275
: '';
7376
window.open(
7477
baseUrl + `${pageToGo}/${encodeBase64(listEntry.aasId)}${repoUrlParam}${infrastructureParam}`,
@@ -88,7 +91,7 @@ export const AasListTableRow = (props: AasTableRowProps) => {
8891
// this can happen if the property is not a MultiLanguageValueOnly type
8992
// e.g. if the property is a AAS Property type (incorrect by specification but possible) string or an error occurs
9093
if (typeof property === 'string') return property;
91-
console.error('Error translating property:', e);
94+
console.error('Error translating property:', e, 'Property:', property);
9295
return '';
9396
}
9497
};

src/app/[locale]/list/_components/filter/SelectRepository.spec.tsx renamed to src/app/[locale]/list/_components/filter/SelectListSource.spec.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from '@jest/globals';
22
import { CustomRender } from 'test-utils/CustomRender';
33
import { fireEvent, screen, waitFor } from '@testing-library/react';
4-
import { SelectRepository } from 'app/[locale]/list/_components/filter/SelectRepository';
4+
import { SelectListSource } from 'app/[locale]/list/_components/filter/SelectListSource';
55
import * as connectionServerActions from 'lib/services/database/infrastructureDatabaseActions';
66

77
jest.mock('./../../../../../lib/services/database/infrastructureDatabaseActions');
@@ -19,8 +19,13 @@ describe('SelectRepository', () => {
1919
});
2020
const repositoryChanged = jest.fn();
2121
(connectionServerActions.getAasRepositoriesIncludingDefault as jest.Mock).mockImplementation(mockDB);
22+
(connectionServerActions.getAasRegistriesIncludingDefault as jest.Mock).mockImplementation(
23+
jest.fn(() => {
24+
return [];
25+
}),
26+
);
2227
CustomRender(
23-
<SelectRepository
28+
<SelectListSource
2429
onSelectedRepositoryChanged={() => {
2530
repositoryChanged();
2631
}}
@@ -31,7 +36,8 @@ describe('SelectRepository', () => {
3136
const select = screen.getByRole('combobox');
3237
fireEvent.mouseDown(select);
3338

34-
const firstElement = screen.getAllByRole('option')[0];
39+
// const firstElement = screen.getAllByRole('option')[0];
40+
const firstElement = screen.getByTestId('repository-select-item-0');
3541
fireEvent.click(firstElement);
3642

3743
expect(repositoryChanged).toHaveBeenCalled();

0 commit comments

Comments
 (0)