From 6ad5f989e5137f9be9ff3b19dd99189bd7e7ab43 Mon Sep 17 00:00:00 2001
From: Pawel Baran <98280057+pawel-baran-se@users.noreply.github.com>
Date: Fri, 17 Jan 2025 09:11:03 +0100
Subject: [PATCH 01/23] style(AAS-List): Update styling of aas list page (#62)
---
src/app/[locale]/list/_components/AasList.tsx | 18 ++-
.../list/_components/AasListDataWrapper.tsx | 110 +++++++++---------
.../list/_components/AasListHeader.tsx | 2 +-
.../list/_components/AasListTableRow.tsx | 39 +++++--
.../_components/filter/SelectRepository.tsx | 4 +-
src/app/[locale]/list/page.tsx | 10 +-
.../_components/DiscoveryListView.tsx | 2 +-
src/components/basics/ListHeader.tsx | 24 ++--
.../basics/listBasics/PictureTableCell.tsx | 4 +-
src/layout/theme/DefaultTheme.tsx | 6 +-
src/layout/theme/theme.ts | 16 ++-
src/lib/util/ToolTipText.tsx | 2 +-
src/locale/de.json | 2 +-
src/locale/en.json | 2 +-
14 files changed, 143 insertions(+), 98 deletions(-)
diff --git a/src/app/[locale]/list/_components/AasList.tsx b/src/app/[locale]/list/_components/AasList.tsx
index 20fd8f70..a22efc1a 100644
--- a/src/app/[locale]/list/_components/AasList.tsx
+++ b/src/app/[locale]/list/_components/AasList.tsx
@@ -36,6 +36,7 @@ export default function AasList(props: AasListProps) {
{ label: t('productDesignationHeading') },
{ label: t('assetIdHeading') },
{ label: t('aasIdHeading') },
+ '',
];
/**
@@ -66,7 +67,12 @@ export default function AasList(props: AasListProps) {
arrow
>
@@ -74,7 +80,14 @@ export default function AasList(props: AasListProps) {
{!!tableHeaders &&
tableHeaders.map((header: { label: string }, index) => (
- {header.label}
+
+ {header.label}
+
))}
@@ -85,7 +98,6 @@ export default function AasList(props: AasListProps) {
-
- {t('subHeader')}
-
-
-
-
-
+
+
+
+
+
+
+ {env.COMPARISON_FEATURE_FLAG && (
+
+ )}
- {env.COMPARISON_FEATURE_FLAG && (
-
- )}
-
- {isLoadingList ? (
-
- ) : (
- <>
- {selectedRepository ? (
- <>
-
-
-
-
-
- {t('page') + ' ' + (currentPage + 1)}
-
-
-
+ {isLoadingList ? (
+
+ ) : (
+ <>
+ {selectedRepository ? (
+ <>
+
+
+
+ {t('page') + ' ' + (currentPage + 1)}
+
+
+
+
+
+
+
+
+ >
+ ) : (
+
+ {t('select-repository')}
- >
- ) : (
-
- {t('select-repository')}
-
- )}
- >
- )}
- >
+ )}
+ >
+ )}
+
+
);
}
diff --git a/src/app/[locale]/list/_components/AasListHeader.tsx b/src/app/[locale]/list/_components/AasListHeader.tsx
index f826fdc1..950c6c1e 100644
--- a/src/app/[locale]/list/_components/AasListHeader.tsx
+++ b/src/app/[locale]/list/_components/AasListHeader.tsx
@@ -6,7 +6,7 @@ export default async function AasListHeader() {
return (
<>
-
+
{t('header')}
>
diff --git a/src/app/[locale]/list/_components/AasListTableRow.tsx b/src/app/[locale]/list/_components/AasListTableRow.tsx
index f06e37b4..c608ff9a 100644
--- a/src/app/[locale]/list/_components/AasListTableRow.tsx
+++ b/src/app/[locale]/list/_components/AasListTableRow.tsx
@@ -1,6 +1,4 @@
-import { Box, Checkbox, TableCell, Typography } from '@mui/material';
-import { encodeBase64 } from 'lib/util/Base64Util';
-import { useRouter } from 'next/navigation';
+import { Box, Checkbox, Skeleton, TableCell, Typography } from '@mui/material';
import { useAasOriginSourceState, useAasState } from 'components/contexts/CurrentAasContext';
import { useNotificationSpawner } from 'lib/hooks/UseNotificationSpawner';
import { ImageWithFallback } from 'components/basics/StyledImageWithFallBack';
@@ -17,6 +15,7 @@ import { ListEntityDto, NameplateValuesDto } from 'lib/services/list-service/Lis
import { getNameplateValuesForAAS } from 'lib/services/list-service/aasListApiActions';
import { MultiLanguageValueOnly } from 'lib/api/basyx-v3/types';
import { useLocale, useTranslations } from 'next-intl';
+import { encodeBase64 } from 'lib/util/Base64Util';
type AasTableRowProps = {
repositoryUrl: string;
@@ -29,8 +28,9 @@ type AasTableRowProps = {
const tableBodyText = {
lineHeight: '150%',
- fontSize: '16px',
+ fontSize: '14px',
color: 'text.primary',
+ wordWrap: 'break-word',
};
export const AasListTableRow = (props: AasTableRowProps) => {
const {
@@ -41,19 +41,20 @@ export const AasListTableRow = (props: AasTableRowProps) => {
selectedAasList,
updateSelectedAasList,
} = props;
- const navigate = useRouter();
const [, setAas] = useAasState();
const [, setAasOriginUrl] = useAasOriginSourceState();
const notificationSpawner = useNotificationSpawner();
const [thumbnailUrl, setThumbnailUrl] = useState('');
const [nameplateData, setNameplateData] = useState();
+ const [isLoading, setIsLoading] = useState(false);
const t = useTranslations('aas-list');
const locale = useLocale();
const navigateToAas = (listEntry: ListEntityDto) => {
setAas(null);
setAasOriginUrl(null);
- if (listEntry.aasId) navigate.push(`/viewer/${encodeBase64(listEntry.aasId)}`);
+ const baseUrl = window.location.origin;
+ window.open(baseUrl + `/viewer/${encodeBase64(listEntry.aasId)}`, '_blank');
};
const translateListText = (property: MultiLanguageValueOnly | undefined) => {
@@ -84,6 +85,7 @@ export const AasListTableRow = (props: AasTableRowProps) => {
useAsyncEffect(async () => {
if (!aasListEntry.aasId) return;
+ setIsLoading(true);
const nameplate = await getNameplateValuesForAAS(repositoryUrl, aasListEntry.aasId);
@@ -92,6 +94,8 @@ export const AasListTableRow = (props: AasTableRowProps) => {
} else {
setNameplateData(nameplate);
}
+
+ setIsLoading(false);
}, [aasListEntry.aasId]);
const showMaxElementsNotification = () => {
@@ -126,19 +130,32 @@ export const AasListTableRow = (props: AasTableRowProps) => {
)}
-
+ navigateToAas(aasListEntry)}
+ />
- {nameplateData && translateListText(nameplateData.manufacturerName)}
+ {!isLoading ? (
+ nameplateData?.manufacturerName && translateListText(nameplateData.manufacturerName)
+ ) : (
+
+ )}
- {nameplateData && tooltipText(translateListText(nameplateData.manufacturerProductDesignation), 80)}
+ {!isLoading ? (
+ nameplateData && tooltipText(translateListText(nameplateData.manufacturerProductDesignation), 80)
+ ) : (
+
+ )}
- {tooltipText(aasListEntry.assetId, 35)}
+ {tooltipText(aasListEntry.assetId, 70)}
- {tooltipText(aasListEntry.aasId, 35)}
+ {tooltipText(aasListEntry.aasId, 70)}
) : (
- {t('repository-dropdown')}
+
+ {t('repository-dropdown')}
+
>
diff --git a/src/app/[locale]/list/page.tsx b/src/app/[locale]/list/page.tsx
index 9f1ea5e6..bb1e5c25 100644
--- a/src/app/[locale]/list/page.tsx
+++ b/src/app/[locale]/list/page.tsx
@@ -1,26 +1,17 @@
'use client';
import { Box } from '@mui/material';
-import { AasListViewDeprecated } from 'app/[locale]/list/_components-deprecated/AasListViewDeprecated';
import ListHeader from 'components/basics/ListHeader';
-import { useEnv } from 'app/env/provider';
import AasListDataWrapper from './_components/AasListDataWrapper';
export default function Page() {
- const env = useEnv();
-
- /**
- * Once the new list implementation is done:
- * we can delete the "_component-deprecated" folder
- * we can remove the "AAS_LIST_V2_FEATURE_FLAG" feature flag and the corresponding render condition.
- */
return (
- {env.AAS_LIST_V2_FEATURE_FLAG ? : }
+
);
diff --git a/src/app/[locale]/viewer/discovery/_components/DiscoveryListTableRow.tsx b/src/app/[locale]/viewer/discovery/_components/DiscoveryListTableRow.tsx
index 2264ec7c..41f31708 100644
--- a/src/app/[locale]/viewer/discovery/_components/DiscoveryListTableRow.tsx
+++ b/src/app/[locale]/viewer/discovery/_components/DiscoveryListTableRow.tsx
@@ -27,13 +27,13 @@ export const DiscoveryListTableRow = (props: DiscoveryListTableRowProps) => {
const navigateToAas = (aasId: string, repoUrl?: string) => {
setAas(null);
- setAasOriginUrl(null)
+ setAasOriginUrl(null);
navigate.push(`/viewer/${encodeBase64(aasId)}${repoUrl ? `?repoUrl=${encodeURI(repoUrl)}` : ''}`);
};
return (
<>
-
+
{aasListEntry.aasId}
@@ -44,7 +44,7 @@ export const DiscoveryListTableRow = (props: DiscoveryListTableRowProps) => {
}
onClick={() => navigateToAas(aasListEntry.aasId, aasListEntry.repositoryUrl)}
- title={intl.formatMessage(messages.mnestix.aasList.titleViewAASButton)}
+ title={intl.formatMessage(messages.mnestix.discoveryList.titleViewAASButton)}
/>
>
diff --git a/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx b/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx
index cd0db572..d3074f7a 100644
--- a/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx
+++ b/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx
@@ -83,7 +83,7 @@ export const DiscoveryListView = () => {
}, []);
const tableHeaders = [
- { label: intl.formatMessage(messages.mnestix.aasList.picture) },
+ { label: intl.formatMessage(messages.mnestix.discoveryList.picture) },
{ label: intl.formatMessage(messages.mnestix.discoveryList.aasIdHeading) },
{ label: intl.formatMessage(messages.mnestix.discoveryList.repositoryUrl) },
];
diff --git a/src/app/env/env.ts b/src/app/env/env.ts
index 9534fa7a..53889dca 100644
--- a/src/app/env/env.ts
+++ b/src/app/env/env.ts
@@ -13,7 +13,6 @@ export const getEnv = async (): Promise => {
COMPARISON_FEATURE_FLAG: process.env.COMPARISON_FEATURE_FLAG?.toLowerCase() === 'true'.toLowerCase(),
TRANSFER_FEATURE_FLAG: process.env.TRANSFER_FEATURE_FLAG?.toLowerCase() === 'true'.toLowerCase(),
AAS_LIST_FEATURE_FLAG: process.env.AAS_LIST_FEATURE_FLAG?.toLowerCase() === 'true'.toLowerCase(),
- AAS_LIST_V2_FEATURE_FLAG: process.env.AAS_LIST_V2_FEATURE_FLAG?.toLowerCase() === 'true'.toLowerCase(),
};
// If BackendAPI is present evaluate the FeatureFlags else they stay the default value
@@ -22,15 +21,6 @@ export const getEnv = async (): Promise => {
process.env.AUTHENTICATION_FEATURE_FLAG?.toLowerCase() === 'true'.toLowerCase();
}
- if (
- !process.env.MNESTIX_BACKEND_API_URL &&
- featureFlags.AAS_LIST_FEATURE_FLAG &&
- !featureFlags.AAS_LIST_V2_FEATURE_FLAG
- ) {
- console.warn('Only AAS_LIST_V2_FEATURE_FLAG environment variables can be set without Mnestix API');
- featureFlags.AAS_LIST_V2_FEATURE_FLAG = true;
- }
-
const otherVariables = {
AD_CLIENT_ID: process.env.AD_CLIENT_ID,
AD_TENANT_ID: process.env.AD_TENANT_ID,
@@ -77,7 +67,6 @@ export type EnvironmentalVariables = {
AUTHENTICATION_FEATURE_FLAG: boolean;
COMPARISON_FEATURE_FLAG: boolean;
AAS_LIST_FEATURE_FLAG: boolean;
- AAS_LIST_V2_FEATURE_FLAG: boolean;
TRANSFER_FEATURE_FLAG: boolean;
DISCOVERY_API_URL: string | undefined;
REGISTRY_API_URL: string | undefined;
diff --git a/src/app/env/provider.tsx b/src/app/env/provider.tsx
index 058f9394..98aed0ef 100644
--- a/src/app/env/provider.tsx
+++ b/src/app/env/provider.tsx
@@ -6,7 +6,6 @@ import { CenteredLoadingSpinner } from 'components/basics/CenteredLoadingSpinner
const initialValues: EnvironmentalVariables = {
AAS_LIST_FEATURE_FLAG: false,
- AAS_LIST_V2_FEATURE_FLAG: false,
COMPARISON_FEATURE_FLAG: false,
TRANSFER_FEATURE_FLAG: false,
AUTHENTICATION_FEATURE_FLAG: false,
diff --git a/src/lib/i18n/de.mnestix.ts b/src/lib/i18n/de.mnestix.ts
index 7c45cd5d..069ea20f 100644
--- a/src/lib/i18n/de.mnestix.ts
+++ b/src/lib/i18n/de.mnestix.ts
@@ -205,7 +205,8 @@ export const deMnestix = {
},
transfer: {
title: 'Import',
- subtitle: 'Füllen sie die folgenden Schritte aus, um eine Verwaltungsschale in ein anderes Repository zu importieren',
+ subtitle:
+ 'Füllen sie die folgenden Schritte aus, um eine Verwaltungsschale in ein anderes Repository zu importieren',
aasRepository: 'AAS Repository',
submodelRepository: 'Submodel Repository',
chooseRepository: 'AAS Repository auswählen',
@@ -219,52 +220,7 @@ export const deMnestix = {
successfullToast: 'Transfer der AAS erfolgreich',
errorToast: 'Transfer der AAS nicht erfolgreich',
partiallyFailedToast: 'Teil des Transfers fehlgeschlagen',
- warningToast: 'Transfer der AAS nur teilweise erfolgreich.'
- },
- aasList: {
- header: 'AAS List',
- subtitle:
- 'Wählen Sie bis zu 3 Verwaltungsschalen zum Vergleichen aus und grenzen Sie die Liste mithilfe des Produktklassenfilters ein.',
- picture: 'Bild',
- manufacturerHeading: 'Hersteller Name',
- productDesignationHeading: 'Hersteller Produktbezeichnung',
- assetIdHeading: 'Asset ID',
- aasIdHeading: 'AAS ID',
- productClassHeading: 'Produktklasse',
- goToCompare: 'Zum Vergleich',
- maxElementsWarning: 'Maximal 3 Elemente selektierbar',
- compareTooltip: 'Vergleichen',
- showAll: 'Alle Produktklassen',
- notAvailable: 'Nicht verfügbar',
- titleComparisonAddButton: 'Füge VWS zum Vergleich hinzu',
- titleProductChipNotAvailable: 'Produktklasse der VWS nicht verfügbar',
- titleViewAASButton: 'VWS anzeigen',
- productClassHint: 'Ergebnisse für Produktklasse',
- productClasses: {
- '27-27': 'Sensorik, sicherheitsgerichtete Sensorik',
- '51-01': 'Antrieb (pneumatics)',
- '51-02': 'Handhabung (pneumatics)',
- '51-03': 'Ventil (pneumatics)',
- '51-04': 'Ventilbaugruppe (pneumatics)',
- '51-05': 'Druckluftaufbereitung (pneumatics)',
- '51-06': 'Vakuumtechnik (pneumatics)',
- '51-07': 'Leitung und Leitungsverbindung (pneumatics)',
- '51-08': 'Pneumatische und elektropneumatische Steuerung (pneumatics)',
- '51-09': 'Dokumentation und Software (pneumatics)',
- '51-41': 'Pumpe (hydraulics)',
- '51-42': 'Motor (hydraulics)',
- '51-43': 'Getriebe (hydraulics)',
- '51-44': 'Ventil Schaltfunktion (hydraulics)',
- '51-45': 'Ventil Stetigfunktion (hydraulics)',
- '51-46': 'Logikventil (hydraulics)',
- '51-47': 'Steuerung (hydraulics)',
- '51-48': 'Zylinder, autarke Achse und elektrohydraulischer Antrieb (hydraulics)',
- '51-49': 'Hydroaggregat (hydraulics)',
- '51-51': 'Hydrospeicher (hydraulics)',
- '51-52': 'Filter (hydraulics)',
- '51-56': 'Leitung und Leitungsverbindung (hydraulics)',
- '51-57': 'Wärmetechnik (hydraulics)',
- },
+ warningToast: 'Transfer der AAS nur teilweise erfolgreich.',
},
themeSettings: {
heading: 'Theme',
@@ -277,6 +233,8 @@ export const deMnestix = {
logoHelperText: 'base64 encoded',
},
discoveryList: {
+ titleViewAASButton: 'VWS anzeigen',
+ picture: 'Bild',
header: 'Verwandte AAS für ID',
aasIdHeading: 'AAS ID',
repositoryUrl: 'Repository Url',
diff --git a/src/lib/i18n/en.mnestix.ts b/src/lib/i18n/en.mnestix.ts
index e5aa7921..9c67c125 100644
--- a/src/lib/i18n/en.mnestix.ts
+++ b/src/lib/i18n/en.mnestix.ts
@@ -216,51 +216,7 @@ export const enMnestix = {
successfullToast: 'Transfer of AAS successful',
errorToast: 'Transfer of AAS not successful',
partiallyFailedToast: 'Failed to transfer element',
- warningToast: 'AAS was only partially transferred.'
- },
- aasList: {
- header: 'AAS List',
- subtitle: 'Select up to 3 AASs to compare and narrow down the list by using the product class filter.',
- picture: 'Picture',
- manufacturerHeading: 'Manufacturer Name',
- productDesignationHeading: 'Manufacturer Product Designation',
- assetIdHeading: 'Asset ID',
- aasIdHeading: 'AAS ID',
- productClassHeading: 'Product Class',
- goToCompare: 'Compare',
- maxElementsWarning: 'Cannot compare more than 3 elements',
- compareTooltip: 'Compare',
- showAll: 'All product classes',
- notAvailable: 'Not available',
- titleComparisonAddButton: 'Add AAS to comparison',
- titleProductChipNotAvailable: 'Product Class of AAS not available',
- titleViewAASButton: 'View AAS',
- productClassHint: 'results for Product Class',
- productClasses: {
- '27-27': 'Sensor technology, safety-related sensor technology',
- '51-01': 'Actuator (pneumatics)',
- '51-02': 'Handling (pneumatics)',
- '51-03': 'Valve (pneumatics)',
- '51-04': 'Valve module (pneumatics)',
- '51-05': 'Compressed air preparation (pneumatics)',
- '51-06': 'Vacuum technology (pneumatics)',
- '51-07': 'Pneumatic Connection technology (pneumatics)',
- '51-08': 'Pneumatic and electropneumatic control system (pneumatics)',
- '51-09': 'Documentation and Software (pneumatics)',
- '51-41': 'Pump (hydraulics)',
- '51-42': 'Motor (hydraulics)',
- '51-43': 'Transmission (hydraulics)',
- '51-44': 'Switching valve (hydraulics)',
- '51-45': 'Continuous control valve (hydraulics)',
- '51-46': 'Two-port-slip-in cartridge valve (hydraulics)',
- '51-47': 'Control system (hydraulics)',
- '51-48': 'Cylinder, electro hydraulic actuator, self contained actuator (hydraulics)',
- '51-49': 'Power unit (hydraulics)',
- '51-51': 'Hydraulic accumulator (hydraulics)',
- '51-52': 'Filter (hydraulics)',
- '51-56': 'Pneumatic connection technology (hydraulics)',
- '51-57': 'Heating technology (hydraulics)',
- },
+ warningToast: 'AAS was only partially transferred.',
},
themeSettings: {
heading: 'Theme',
@@ -273,6 +229,8 @@ export const enMnestix = {
logoHelperText: 'base64 encoded',
},
discoveryList: {
+ titleViewAASButton: 'View AAS',
+ picture: 'Picture',
header: 'Related AAS to ID',
aasIdHeading: 'AAS ID',
repositoryUrl: 'Repository Url',
diff --git a/src/lib/services/list-service/ListService.ts b/src/lib/services/list-service/ListService.ts
index c7f64f07..dfb735e3 100644
--- a/src/lib/services/list-service/ListService.ts
+++ b/src/lib/services/list-service/ListService.ts
@@ -62,6 +62,14 @@ export class ListService {
return new ListService(targetAasRepositoryClient, targetSubmodelRepositoryClient);
}
+ /**
+ * Returns all AASs from the chosen repository.
+ * Special Behaviour: If the AssetInformation contains a specificAssetId with the name "aasListFilterId",
+ * the whole AAS is filtered out and not returned from this service.
+ * This logic is needed to hide the configuration AASs created by the mnestix-api.
+ * @param limit
+ * @param cursor
+ */
async getAasListEntities(limit: number, cursor?: string): Promise {
const response = await this.targetAasRepositoryClient.getAllAssetAdministrationShells(limit, cursor);
@@ -72,11 +80,18 @@ export class ListService {
const { result: assetAdministrationShells, paging_metadata } = response.result;
const nextCursor = paging_metadata.cursor;
- const aasListDtos = assetAdministrationShells.map((aas) => ({
- aasId: aas.id,
- assetId: aas.assetInformation?.globalAssetId ?? '',
- thumbnail: aas.assetInformation?.defaultThumbnail?.path ?? '',
- }));
+ const aasListDtos = assetAdministrationShells
+ .filter((aas) => {
+ const aasToRemove = aas.assetInformation.specificAssetIds?.find(
+ (specificAssetId) => specificAssetId.name === 'aasListFilterId',
+ );
+ return !aasToRemove;
+ })
+ .map((aas) => ({
+ aasId: aas.id,
+ assetId: aas.assetInformation?.globalAssetId ?? '',
+ thumbnail: aas.assetInformation?.defaultThumbnail?.path ?? '',
+ }));
return { success: true, entities: aasListDtos, cursor: nextCursor };
}
diff --git a/src/locale/de.json b/src/locale/de.json
index d101f1a0..5fa411b9 100644
--- a/src/locale/de.json
+++ b/src/locale/de.json
@@ -14,7 +14,9 @@
"select-repository": "Bitte wählen Sie ein Repository aus",
"titleComparisonAddButton": "Füge VWS zum Vergleich hinzu",
"titleViewAASButton": "VWS anzeigen",
- "maxElementsWarning": "Maximal 3 Elemente selektierbar"
+ "maxElementsWarning": "Maximal 3 Elemente selektierbar",
+ "goToCompare": "Zum Vergleich",
+ "compareTooltip": "Vergleichen"
},
"dashboard": {
"welcome-text": "Willkommen bei Mnestix",
diff --git a/src/locale/en.json b/src/locale/en.json
index 84a581a7..dbf2e6f9 100644
--- a/src/locale/en.json
+++ b/src/locale/en.json
@@ -14,7 +14,9 @@
"select-repository": "Please select a repository",
"titleComparisonAddButton": "Add AAS to comparison",
"titleViewAASButton": "View AAS",
- "maxElementsWarning": "Cannot compare more than 3 elements"
+ "maxElementsWarning": "Cannot compare more than 3 elements",
+ "goToCompare": "Compare",
+ "compareTooltip": "Compare"
},
"dashboard": {
"welcome-text": "Welcome to Mnestix",
From 0ffc1feeebd36277f9eb4239c0c6fffc3f2e358d Mon Sep 17 00:00:00 2001
From: Jonathan Sigrist
Date: Wed, 22 Jan 2025 11:23:17 +0100
Subject: [PATCH 05/23] fix(submodel-visualization): show the first value if no
language matches (#73)
* if the requested translation is not present in a MultiLanguageProperty use the first entry
* do not translate generic messages in the ListHeader.tsx component
---
src/app/[locale]/list/page.tsx | 4 +++-
.../viewer/discovery/_components/DiscoveryListView.tsx | 5 ++++-
src/components/basics/ListHeader.tsx | 9 +++------
src/global.d.ts | 2 +-
src/lib/util/SubmodelResolverUtil.ts | 2 +-
5 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/app/[locale]/list/page.tsx b/src/app/[locale]/list/page.tsx
index bb1e5c25..f95657af 100644
--- a/src/app/[locale]/list/page.tsx
+++ b/src/app/[locale]/list/page.tsx
@@ -3,13 +3,15 @@
import { Box } from '@mui/material';
import ListHeader from 'components/basics/ListHeader';
import AasListDataWrapper from './_components/AasListDataWrapper';
+import { useTranslations } from 'next-intl';
export default function Page() {
+ const t = useTranslations('aas-list');
return (
-
+
diff --git a/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx b/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx
index d3074f7a..e6eab871 100644
--- a/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx
+++ b/src/app/[locale]/viewer/discovery/_components/DiscoveryListView.tsx
@@ -16,6 +16,7 @@ import { performDiscoveryAasSearch, performRegistryAasSearch } from 'lib/service
import { performSearchAasFromAllRepositories } from 'lib/services/repository-access/repositorySearchActions';
import { RepoSearchResult } from 'lib/services/repository-access/RepositorySearchService';
import { AssetAdministrationShell } from '@aas-core-works/aas-core3.0-typescript/types';
+import { useTranslations } from 'next-intl';
async function getRepositoryUrl(aasId: string): Promise {
const registrySearchResult = await performRegistryAasSearch(aasId);
@@ -39,6 +40,8 @@ export const DiscoveryListView = () => {
const encodedAasId = searchParams.get('aasId');
const aasId = encodedAasId ? decodeURI(encodedAasId) : undefined;
+ const t = useTranslations('aas-list');
+
useAsyncEffect(async () => {
setIsLoadingList(true);
const entryList: IDiscoveryListEntry[] = [];
@@ -90,7 +93,7 @@ export const DiscoveryListView = () => {
return (
<>
-
+
{isLoadingList && }
{!isLoadingList && !isError && (
<>
diff --git a/src/components/basics/ListHeader.tsx b/src/components/basics/ListHeader.tsx
index a3370b8c..24fcc79c 100644
--- a/src/components/basics/ListHeader.tsx
+++ b/src/components/basics/ListHeader.tsx
@@ -1,27 +1,24 @@
'use client';
import { Typography } from '@mui/material';
-import { useTranslations } from 'next-intl';
type ListHeaderProps = {
- namespace: string;
header: string;
subHeader?: string;
optionalID?: string;
};
export default function ListHeader(props: ListHeaderProps) {
- const { namespace, header, subHeader, optionalID } = props;
- const t = useTranslations(namespace);
+ const { header, subHeader, optionalID } = props;
return (
<>
- {t(header)}
+ {header}
{optionalID && ` "${optionalID}"`}
{subHeader && (
- {t(subHeader)}
+ {subHeader}
)}
>
diff --git a/src/global.d.ts b/src/global.d.ts
index 6145fbf4..3698b580 100644
--- a/src/global.d.ts
+++ b/src/global.d.ts
@@ -1,7 +1,7 @@
import en from './locale/en.json';
import userPluginEn from './user-plugins/locale/en.json';
-type Messages = typeof en & userPluginEn;
+type Messages = typeof en & typeof userPluginEn;
declare global {
interface Window {
diff --git a/src/lib/util/SubmodelResolverUtil.ts b/src/lib/util/SubmodelResolverUtil.ts
index 12bf33d5..e1da78c7 100644
--- a/src/lib/util/SubmodelResolverUtil.ts
+++ b/src/lib/util/SubmodelResolverUtil.ts
@@ -14,7 +14,7 @@ import { getKeyType } from 'lib/util/KeyTypeUtil';
export function getTranslationTextNext(element: MultiLanguageProperty, locale: string) {
const value = element.value?.find((el) => el.language == locale)?.text;
- return value || null;
+ return value || element.value?.at(0)?.text || null;
}
export function findSubmodelElementByIdShort(
From b68574378551e18aedf8b7db9f2a382ab018b039 Mon Sep 17 00:00:00 2001
From: NilsXitaso
Date: Wed, 22 Jan 2025 12:54:16 +0100
Subject: [PATCH 06/23] chore(README): Bring ReadMe to Wiki (#76)
Signed-off-by: NilsXitaso
Co-authored-by: melanie.gail
---
README.md | 692 +-----------------------------------------------------
1 file changed, 7 insertions(+), 685 deletions(-)
diff --git a/README.md b/README.md
index a58fc899..5ba84682 100644
--- a/README.md
+++ b/README.md
@@ -27,211 +27,7 @@ implementation of standardized digital twins. It opens the way for use cases suc
You can find a demo [here](https://mnestix-prod.azurewebsites.net/).
Some screenshots can be found in the [screenshots folder](screenshots).
-### **If you need support feel free to contact us through our
-website [here](https://xitaso.com/kompetenzen/mnestix/#support).**
-
-## Quickstart
-
-All you need to start your first Mnestix instance is the `compose.yml` (or clone the repository).
-In the root directory run the following command and open http://localhost:3000 in your web browser.
-
-```shell
-docker compose up
-```
-
-If you want to further configure your mnestix instance, read about [configuration](#mnestix-configuration-settings).
-
-## Getting started with developing
-
-### Development technologies
-
-- Next.js
-
-### Prerequisites
-
-Before you begin, ensure you have the following tools installed on your system:
-
-1. **Node.js**
-
-2. **Yarn**
-
-3. **Docker**: Docker is required to create and run the application containers.
-
- - [Install Docker](https://docs.docker.com/get-docker/)
-
-4. **Docker Compose**: Docker Compose is a tool for defining and running multi-container Docker applications.
- - [Install Docker Compose](https://docs.docker.com/compose/install/)
-
-Windows users may use WSL for their docker instance.
-
-### Run Mnestix as Complete AAS Application
-
-The easiest way to get Mnestix up and running is by using the prepared development environment.
-This setup includes:
-
-- Mnestix Browser (This repository)
-- Mnestix Backend
-- BaSyx Repository
-- BaSyx Discovery Service
-- BaSyx Registry
-- BaSyx Submodel Registry
-
-To start all mentioned services together, run the following command:
-
-```shell
-yarn docker:dev
-```
-
-This will build the Mnestix Browser and start all mentioned services with a default configuration, to adapt this setup
-have a look at [configuration](#mnestix-configuration-settings).
-The Mnestix Browser is now running on http://localhost:3000.
-
-### Run Mnestix through IDE
-
-If you want to start the browser through your IDE separately start BaSyx and the backend with
-
-```shell
-yarn docker:backend
-```
-
-In your IDE you can then simply start the dev environment with hot reloading by running
-
-```shell
-yarn dev
-```
-
-The Mnestix Browser is now running on http://localhost:3000 and will update on changed files.
-
-If you want to activate debug breakpoints in the code, you may have to open the website through a debug environment:
-
-- In `JetBrains WebStorm` you can run a debug browser with the `JS Debug` run configuration.
-- In `Visual Studio Code` you can set up a debug browser by creating a `launch.json` file in the `Run and Debug` tab and
- create a run configuration for your preferred browser.
-
-You may need to set the initial URL to http://localhost:3000.
-
-### Other launch options
-
-To check what other options exist to run the Mnestix Browser, see the yarn scripts in `package.json`. Highlights are:
-
-- `yarn dev` to start the browser in a hot reloading dev environment.
-- `yarn prettier`, `yarn format` and `yarn lint` to apply code formatting and linting.
-- `yarn test` and `yarn test:headless` to run cypress tests locally.
-- `yarn docker:prod` will build everything with the production flag.
-- `yarn docker:test` will run all tests in the docker environment.
-- `yarn docker:prune` will stop all docker containers, remove them from the list and prune all volumes. Start with a
- blank slate :)
-- `yarn docker:keycloak` will setup a local keycloak instance and start Mnestix with keycloak support enabled
-
-## Secret environment variables
-
-You can (and should) create your personal `.env` file in the root directory.
-Simply rename `.env.example` to `.env` and enter your secrets.
-The secrets may be arbitrary strings.
-
-This `.env` file will be used automatically by docker compose and Next.js.
-
-```yaml
-AD_SECRET_VALUE: '<>'
-MNESTIX_BACKEND_API_KEY: '<>'
-NEXTAUTH_SECRET: '<>'
-```
-
-> ⚠️ **Important:** If you have not configured these secrets, a public secret will be used as a fallback!
-
-## Docker Compose files
-
-- **compose.yml** - runs Mnestix Browser in production environment. Production image will be build if not found in local
- Docker Image Cache.
- **Mnestix Browser on port 3000 - http://localhost:3000**
-
-
-- **docker-compose/compose.frontend.yml** - runs Mnestix Browser with a Basyx environment (AAS-Environment with MongoDB,
- Discovery Service, AAS/Submodel Registry) but without the Mnestix-API.
- **Mnestix Browser on port 3000 - http://localhost:3000**
-
-- **docker-compose/compose.dev.yml** - override file to run Mnestix Browser in a development environment. A development
- image will be built if it is not found in the local Docker Image Cache.
- **Mnestix Browser on port 3000 - http://localhost:3000**
- **Mnestix Api on port 5064 - http://localhost:5064**
- **AAS Repo on port 8081 - http://localhost:8081/swagger-ui/index.html**
-
-- **docker-compose/compose.test.yml** - override file used to configure and run end-to-end (E2E) tests using Cypress.
- When this file is executed, it will start the necessary services for the application and execute the Cypress tests.
- If any test fails, the results and logs will be saved in a designated directory for further analysis.
-
-- **docker-compose/compose.azure_ad.yml** - override file to activate authentication using Azure Entra ID.
- You will need to provide your own Authentication Endpoint.
- Configuration can be found [here](#using-azure-entra-id).
+
+[![Made by XITASO](https://img.shields.io/badge/Made_by_XITASO-005962?style=flat-square)](https://xitaso.com/)
+[![MIT License](https://img.shields.io/badge/License-MIT-005962.svg?style=flat-square)](https://choosealicense.com/licenses/mit/)
+[![Yarn License](https://img.shields.io/badge/YARN-V1.22.22-005962?style=flat-square)]()
+[![Join our Community](https://img.shields.io/badge/Join_our_Community-005962?style=flat-square)](https://xitaso.com/kompetenzen/mnestix/#support)
+
+### Welcome to the Mnestix Community!
+
+Mnestix Browser is an open source software designed to simplify the implementation of the Asset Administration Shell.
+Together
+with increasing contributions from users and developers, a growing community is working on further development under the
+leadership of XITASO, a leading high-end software development company in the engineering industry.
+Mnestix Browser is the perfect tool to demonstrate the power and potential of AAS (**Asset Administration Shells**) for
+the
+implementation of standardized digital twins. It opens the way for use cases such as the Digital Product Passport (DPP).
+
+You can find a demo [here](https://mnestix-prod.azurewebsites.net/).
+Some screenshots can be found in the [screenshots folder](https://github.com/eclipse-mnestix/mnestix-browser/tree/main/screenshots).
+
+### **If you need support feel free to contact us through our website [here](https://xitaso.com/kompetenzen/mnestix/#support).**
+
+## Quickstart
+
+All you need to start your first Mnestix instance is the `compose.yml` (or clone the repository).
+In the root directory run the following command and open http://localhost:3000 in your web browser.
+
+```shell
+docker compose up
+```
+
+If you want to further configure your mnestix instance, read about [configuration](mnestix-configuration-settings).
\ No newline at end of file
diff --git a/wiki/How-to-Create-Custom-Submodel-Visualizations.md b/wiki/How-to-Create-Custom-Submodel-Visualizations.md
new file mode 100644
index 00000000..9d109f83
--- /dev/null
+++ b/wiki/How-to-Create-Custom-Submodel-Visualizations.md
@@ -0,0 +1,219 @@
+One of Mnestix’ goals is to make it as easy as possible to visualize data.
+
+Out of the box, Mnestix offers a general visualization for submodels. Additionally, Mnestix offers a selection of tailored visualizations for standardized and not standardized submodels.
+Those include for example visualizations for the Product Carbon Footprint submodel, the Hierarchical Structures submodel and the Time Series submodel. Additionally, Mnestix provides tailored visualizations for a selection of submodel elements, such as Address components, Document components and Entity components.
+
+In order to realize your own use cases, Mnestix provides a means to implement your own custom visualizations for submodels and submodel elements.
+The following steps will explain how you can provide these visualizations.
+
+![image](https://github.com/user-attachments/assets/87635f84-e5ee-4f69-9113-8300f495fa28)
+
+> [!TIP]
+> For a starting point we provide an example submodel visualization at [SoftwareNameplate](https://github.com/eclipse-mnestix/mnestix-browser-example-submodel-visualizations).
+> We encourage you to use this repository as a template for your own visualization.
+> Throughout this guide are tips based on this submodel visualization.
+
+
+# 1. Fork and Clone the Mnestix GitHub repository
+
+> [!NOTE]
+> If you are not planning on contributing to Mnestix you can also skip the fork and directly clone the Mnestix repository. You will not be able to create branches and pull requests this way.
+
+## Fork Mnestix
+
+As for any other contribution to Mnestix, you will have to start by forking the GitHub repository.
+You may fork either the [main branch](https://github.com/eclipse-mnestix/mnestix-browser) for stable release code or the [dev branch](https://github.com/eclipse-mnestix/mnestix-browser/tree/dev) for features which may still be under active development.
+On the repository page you will then have the option to fork the code to your own account.
+
+![mnestix-fork](https://github.com/user-attachments/assets/d33fac6d-c8b0-4139-a00e-b0646367b0ce)
+
+## Clone Mnestix
+
+Clone the Mnestix code from the GitHub repository.
+You may clone either the [main branch](https://github.com/eclipse-mnestix/mnestix-browser) for stable release code or the [dev branch](https://github.com/eclipse-mnestix/mnestix-browser/tree/dev) for features which may still be under active development.
+If you have forked the Mnestix repository in the previous task, clone from your private repository.
+
+## Checking out Mnestix
+
+It is time to check if everything is set up correctly.
+In this guide we assume you have installed docker and node correctly.
+For a full guide on how to develop locally please consider our [Development guide](https://github.com/eclipse-mnestix/mnestix-browser/wiki/Getting-started-with-developing).
+All commands shown should be executed in the root directory of Mnestix.
+
+First you need to install all required packages.
+This can be done with `yarn install` and may take some time depending on your network connection.
+If you have problems executing yarn, you might need to enable it using `corepack enable` first.
+
+Now you can start up all background services as docker containers.
+We provide a few node scripts to ease the startup process.
+During development `yarn docker:backend` will suffice in most cases.
+For a full overview please check out the [compose guide](https://github.com/eclipse-mnestix/mnestix-browser/wiki/Docker-Compose-Files).
+
+To start the Mnestix browser you may use `yarn dev`.
+To make sure debugging and hot-reloading works as expected you might instead use `yarn debug`.
+You can now open `localhost:3000` in your internet browser and should see the Mnestix dashboard.
+It might take a few extra seconds at the first time as node is building your project on the go.
+
+> [!Tip]
+> You can try to find the Mnestix AAS in the list or search for it on the dashboard directly by entering its ID `https://vws.xitaso.com/aas/mnestix`.
+
+# 2. Create your React component
+
+We suggest to create a directory for your submodel visualization inside `src/user-plugins/submodels`.
+
+> [!TIP]
+> To clone the software nameplate you may go into the `src/user-plugins/submodels/` directory and run `git clone https://github.com/eclipse-mnestix/mnestix-browser-example-submodel-visualizations.git`.
+> You can browse the example AAS for the SoftwareNameplate with the ID `https://vws.xitaso.com/aas/mnestix` inside the Mnestix browser.
+
+You can find all currently existing submodel visualizations at the following path: `src/app/[locale]/viewer/_components/submodel`.
+You might want to have a look at them for further examples.
+
+## Creating a visualization for a submodel
+
+After you created the sub-directory for your own visualization, you can create your `.tsx`-file and start developing the component.
+Custom submodel visualizations use the input type `SubmodelVisualizationProps`, which contains the submodel data as `AAS-core-3` type.
+
+You can use this stump to develop a custom submodel visualization:
+
+```tsx
+import { SubmodelVisualizationProps} from 'app/[locale]/viewer/_components/submodel/SubmodelVisualizationProps';
+
+export default function CustomSubmodel({submodel}: SubmodelVisualizationProps){
+ return (
+
This is the custom visualization for submodel {submodel.idShort}
+ );
+}
+```
+
+> [!TIP]
+> For now the custom visualization exists but will not be shown for the SoftwareNameplate submodel.
+> We see the generic overview of submodel data.
+>
+>
+
+## Map the visualization
+
+In order for Mnestix to automatically use your visualization, you have to provide the mapping between your visualization and the semantic id which your custom visualization should be used for.
+This is done in the file `src/app/[locale]/viewer/_components/submodel/SubmodelsCustomVisualizationMap.ts` which looks similar to this:
+
+```ts
+export const submodelsCustomVisualizationMap = {
+ [SubmodelSemanticId.CoffeeConsumptionContainer]: CoffeeConsumptionDetail,
+ [SubmodelSemanticId.CarbonFootprint]: CarbonFootprintDetail,
+ [SubmodelSemanticId.CarbonFootprintIRDI]: CarbonFootprintDetail,
+ [SubmodelSemanticId.ReferenceCounterContainer]: ReferenceCounterDetail,
+ [SubmodelSemanticId.TimeSeries]: TimeSeriesDetail,
+ [SubmodelSemanticId.HierarchicalStructuresV10]: HierarchicalStructuresDetail,
+ [SubmodelSemanticId.HierarchicalStructuresV11]: HierarchicalStructuresDetail,
+ [SubmodelSemanticId.BillOfApplications]: BillOfApplicationsDetail,
+ [/*Your semantic id as a string*/]: /*React component name*/,
+};
+```
+
+Just add an entry containing the semantic id as a key and your React component as the value.
+Important: Don’t forget to import your React component at the top of the file!
+
+> [!NOTE]
+> You might also want to add your semantic id to the `SubmodelSemanticId`-enum used in the examples above.
+> This is not required, you can use a simple string as the key.
+> But it may make particular sence for standardized submodels.
+
+
+> [!TIP]
+> For the SoftwareNameplate the added mapping line will be `['https://admin-shell.io/idta/SoftwareNameplate/1/0']: SoftwareNameplateDetail,`.
+> We see the visualization now, but are still lacking the internationalization.
+>
+>
+
+# 3. Reading data from your submodel
+
+You probably want to display some information from the submodel.
+We provide you with a convenience method to search for a specific value in the submodel.
+Import it at the top of your file
+```ts
+import { findValueByIdShort } from 'lib/util/SubmodelResolverUtil';
+```
+and use it in your component
+```ts
+const value = findValueByIdShort(submodel.submodelElements, 'MyIDshort', 'en');
+```
+
+It will automatically return the requested language value for a MultiLanguageProperty.
+
+# 4. Internationalization
+
+We support internationalization for both submodel data in MultiLanguageProperty fields as well as predefined messages.
+Make sure to import the correct hooks on top of the file.
+```ts
+import { useLocale, useTranslations } from 'next-intl';
+```
+
+## Using current locale in MultiLanguageProperty
+
+You can use the `findValueByIdShort` method with your preferred locale as a parameter.
+This may be changed to always use the currently selected language by calling the `useLocale` hook.
+
+```ts
+const locale = useLocale();
+const value = findValueByIdShort(submodel.submodelElements, 'MyIDshort', locale);
+```
+
+## Using current locale for internationalized messages
+
+We support message internationalization by the `useTranslations` hook.
+To keep things organized we provide a directory for all user-plugin translations at `src/user-plugins/locale`.
+Add your translations in each locale file you want to support.
+Be aware that these files is shared by all user-plugins so merge the files individually and not just overwrite the content.
+
+You may now access the localized messages in your component by getting the translations for your submodel and then selecting the actual message.
+```tsx
+const t = useTranslations('user-plugins.submodels.YourCustomSubmodel');
+return <> {t('YourMessage')} >;
+```
+
+For a full documentation of what is possible with next-intl visit their [website](https://next-intl.dev/docs/usage/messages).
+
+> [!TIP]
+> We have provided the locale files in the repository, but you still need to merge them with the user-plugin locale files.
+> The merged file for `locale/en.json` whould look something like this:
+> ```json
+> {
+> "user-plugins": {
+> "submodels": {
+> "hello-world-component": {
+> "title": "Hello World!"
+> },
+> "SoftwareNameplate": {
+> "welcome": "Welcome to Mnestix by",
+> "slogan": "Asset Administration Shell made easy!",
+> "versionInfo": "This is Mnestix version {version}. It was released on {releaseDate}."
+> }
+> }
+> }
+> }
+> ```
+> Now the submodel visualization will show the translated values from the internationalization file.
+>
+>
+
+
+# 5. (Optional) Create a pull request
+
+Especially when you are creating a visualization for a standardized submodel, we encourage you to contribute it to the Open Source Mnestix repository, so that others can profit from it as well! This can be done by creating a pull request on the GitHub page, like seen in the following picture:
+
+![mnestix-pull-request](https://github.com/user-attachments/assets/2966ad7a-702f-4e00-bde8-a3554a0faed3)
+
+After clicking on “New pull request”, you can select “Compare across forks” and select your own repository, like seen in the picture below:
+
+![mnestix-compare-changes](https://github.com/user-attachments/assets/b9167444-2117-48fa-8fc0-b399f84577d7)
+
+Make sure to select the dev branch as the base branch!
+
+After you have created the pull request, it will get reviewed and merged, as soon as everything is fine and the request got approved.
+
+In case you don’t want to share your visualization with the public, you don’t have to create the pull request. Just be aware, that your project will from now on live in its own repository and not automatically get any updates from the main repository.
+In order to get updates, you will have to manually merge the main repository in to your forked project with every new update. Furthermore, you have to build and publish the docker image by yourself if you wish to use your custom visualization in a productive environment.
+
+
+
+
\ No newline at end of file
diff --git a/wiki/Keycloak-Configuration.md b/wiki/Keycloak-Configuration.md
new file mode 100644
index 00000000..e771a953
--- /dev/null
+++ b/wiki/Keycloak-Configuration.md
@@ -0,0 +1,52 @@
+> **Note:** Keycloak support is available starting from version 1.1.0 and above.
+>
+> For Mnesitx API configuration details, please refer to the API documentation available
+> on [Docker Hub](https://hub.docker.com/r/mnestix/mnestix-api).
+
+### Setting Up Keycloak for Docker Development
+
+To start Mnestix along with Keycloak as the authorization server, use one of the following commands:
+
+```sh
+docker compose -f compose.yml -f docker-compose/compose.dev.yml -f docker-compose/compose.keycloak.yml up -d
+```
+
+or, alternatively:
+
+```sh
+yarn docker:keycloak
+```
+
+On the first startup, the Keycloak Docker image (`docker-compose/data/keycloak/Dockerfile`) will be built with an
+initializer configured for the BaSyx repository.
+This setup ensures that localhost can be resolved within the Docker network. Additionally, a preconfigured Keycloak
+realm (`docker-compose/data/keycloak/realm/BaSyx-realm.json`) will be imported,
+eliminating the need for any initial Keycloak configuration.
+
+The Keycloak Admin Console will be accessible at [http://localhost:8080/admin](http://localhost:8080/admin).
+
+For initial access, use the following temporary credentials:
+
+- **Username:** admin
+- **Password:** admin
+
+A test user is preconfigured with the following credentials allowing login to Mnestix Browser:
+
+- **Username:** test
+- **Password:** test
+
+### Configuration Variables for Keycloak Setup
+
+`KEYCLOAK_LOCAL_URL`:
+
+- **Local Development:** This variable should be left empty when running Mnestix in a local browser environment.
+- **Docker Environment:** When running in a Docker environment, set this variable to `localhost:8080` to enable user
+ credential input. In Docker, the token, user info, and other endpoints will function correctly within the Docker
+ network.
+
+`NEXTAUTH_URL`: Required variable to configure redirect URL for NextAuth.
+
+`NEXTAUTH_SECRET`: Required variable used to encrypt the NextAuth.js JWT, and to hash email verification tokens.
+
+> ⚠️ **Important:** Ensure that you update any confidential variables from their default values before deploying to a
+> production environment.
\ No newline at end of file
diff --git a/wiki/Maintaining.md b/wiki/Maintaining.md
new file mode 100644
index 00000000..f46a05e8
--- /dev/null
+++ b/wiki/Maintaining.md
@@ -0,0 +1,76 @@
+### Setting up VSCode
+
+#### Extensions
+
+See `.vscode/extensions.json` for a list of recommended extensions.
+VSCode will suggest to install them when opening the project.
+
+#### Settings
+
+See `.vscode/settings.json` for defined workspace settings.
+
+### Setting up Rider
+
+Check the configurations for Rider under `.idea/` folder
+
+### Installing and adding/removing frontend packages
+
+### Formatting & Linting
+
+We use Prettier and ESLint to keep our frontend code clean. Having a ESLint warning **will break the pipeline**. It's
+therefore always a good idea to run `yarn format` and `yarn lint` before you commit.
+
+#### Run prettier check
+
+```sh
+yarn prettier
+```
+
+#### Run prettier (be aware, this changes files!)
+
+```sh
+yarn format
+```
+
+#### Check your code for formatting issues
+
+```sh
+yarn lint
+```
+
+If you want specific files or folders to be excluded from linting (e.g. generated files), you can add them
+to `.eslintignore` and `.prettierignore`
+
+### Cypress Testing
+
+We use Cypress for End-to-End-Testing. In order to navigate to the right folder and run Cypress you can use the
+following command. In order to use cypress testing the Mnestix Browser must be running.
+
+#### Open the cypress application
+
+```sh
+yarn test
+```
+
+#### Run cypress headless (runs all tests inside the integration folder)
+
+```sh
+yarn test:headless
+```
+
+Cypress will put videos and screenshots of the tests inside the cypress folder.
+
+In order to run your own E2E-Tests you can put your test files in `/cypress/e2e`.
+
+In the `fixtures` folder you can put data to use in your E2E-Tests as json files.
+
+If you have commands you want to use in multiple tests you can put them into the `commands.ts` file inside
+the `support` folder.
+Don't forget to write the method header of your custom commands inside the `e2e.ts` file as well. This way the IDE
+will stop marking your custom commands as wrong.
+
+### Reverse Proxy Configuration
+
+The YARP proxy route `/repo/shells` now limits resource and list returns to 104 elements due to the lack of pagination
+support.
+This change aims to prevent server overload and ensure smoother navigation through resource lists.
\ No newline at end of file
diff --git a/wiki/Mnestix-Configuration-Settings.md b/wiki/Mnestix-Configuration-Settings.md
new file mode 100644
index 00000000..2b93135f
--- /dev/null
+++ b/wiki/Mnestix-Configuration-Settings.md
@@ -0,0 +1,318 @@
+### Frontend Configuration
+
+Mnestix provides the following configuration options. You can adapt the values in your docker compose file.
+
+| Name | Default value | Description | required |
+|---------------------------------------|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
+| `DISCOVERY_API_URL` | | Address of the Discovery Service to find an AAS for an Asset | required |
+| `REGISTRY_API_URL` | | Address of the AAS Registry Service to retrieve the related descriptor for an AAS | optional |
+| `SUBMODEL_REGISTRY_API_URL` | | Address of the Submodel Registry Service to retrieve the related descriptor for a Submodel | optional |
+| `AAS_REPO_API_URL` | | Default AAS Repository to display when AAS Id is not in AAS Registry | required |
+| `SUBMODEL_REPO_API_URL` | | Default Submodel Repository to display when Submodel Id is not in Submodel Registry | required |
+| `MNESTIX_BACKEND_API_URL` | | Mnestix Backend with a lot of business comfort features like the Repository-Proxy or the Template builder | optional |
+| `AAS_LIST_FEATURE_FLAG` | false | Enables or disables the AasList in the frontend. This only works in combination with `Features__AllowRetrievingAllShellsAndSubmodels` being set to `true` (Needs the Mnestix Backend to work) | optional |
+| `AAS_LIST_V2_FEATURE_FLAG` | false | The functionality controlled by this flag is under active development and may change without notice. Please see [details](#aas-list-v2-feature-details) | optional |
+| `TRANSFER_FEATURE_FLAG` | false | Enables or disables the Transfer Feature in the frontend. If enabled, it is possible to import a viewed AAS to a configured repository. This feature is currently being developed. | optional |
+| `AUTHENTICATION_FEATURE_FLAG` | false | Enable or disable the authentication in the frontend. (Needs the Mnestix Backend to work) | optional |
+| `COMPARISON_FEATURE_FLAG` | false | Enables or disables the comparison feature. | optional |
+| `LOCK_TIMESERIES_PERIOD_FEATURE_FLAG` | false | Enables or disables the selection of the timerange in the TimeSeries submodel. | optional |
+| `THEME_PRIMARY_COLOR` | Mnestix Primary Color | Changes the primary color of Mnestix Browser, e.g. #00ff00. The following formats are supported: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color() | optional |
+| `THEME_SECONDARY_COLOR` | Mnestix Secondary Color | Changes the secondary color of Mnestix Browser, e.g. #0d2. The following formats are supported: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color() | optional |
+| `THEME_LOGO_MIME_TYPE` | | Used in parsing the logo mounted `-v /path/to/logo:/app/public/logo` the mime type is needed, e.g. `image/svg+xml`, `image/png`, `image/jpg` | optional |
+| `THEME_LOGO_URL` | | This variable **overwrites** the Logo in the theme, and thus the environment variable `THEME_LOGO_MIME_TYPE` will not be evaluated and it is not necessary to mount the image as specified below | optional |
+| `KEYCLOAK_ENABLED` | false | By default, it is set to false, meaning Keycloak authentication will be disabled, and the default authentication method will be Azure Entra ID. If you set this variable to true, Keycloak authentication will be enabled instead. | optional |
+| `KEYCLOAK_CLIENT_ID` | mnestix-browser-client-demo | Configuration variable that specifies the client unique identifier used by your application when connecting to the Keycloak server. | optional |
+| `KEYCLOAK_ISSUER` | | Configuration variable that specifies the URL of the Keycloak servers issuer endpoint. This endpoint provides the base URL for the Keycloak server that issues tokens and handles authentication requests | optional |
+| `KEYCLOAK_LOCAL_URL` | | Optional configuration variable specifically used for development environments within Docker. This allows your application to connect to a Keycloak instance running in a Docker container | optional |
+| `KEYCLOAK_REALM` | BaSyx | Configuration variable that specifies the name of the Keycloak realm your application will use for authentication and authorization. | optional |
+| `IMPRINT_URL` | | Address that will be used in the imprint link. Will only show the link, if a value has been set. | optional |
+| `DATA_PRIVACY_URL` | | Address that will be used in the data privacy link. Will only show the link, if a value has been set. | optional |
+
+### How to set a custom logo
+
+There are multiple ways to set a logo, you can either use Option 1 or Option 2:
+
+#### Option 1
+
+First you need to mount your logo to the container, e.g. by adding it to the docker compose file
+
+```yaml
+environment:
+ - THEME_LOGO_MIME_TYPE: 'image/svg+xml'
+---
+volumes:
+ - /path/to/my/logo.svg:/app/public/logo
+```
+
+When using the provided [`compose.yaml` File](https://github.com/eclipse-mnestix/mnestix-browser/blob/main/compose.yml) you can just replace the [image in the
+`data` folder](https://github.com/eclipse-mnestix/mnestix-browser/tree/main/docker-compose/data/logo.svg) with your preferred logo.
+
+Remember to set the mime type correctly in order for the browser to parse your image correctly.
+Only image mime types are allowed.
+https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
+
+#### Option 2
+
+This version overwrites the previous settings, you can either use one or the other.
+To use this just set an environment variable to a link hosted that is publicly accessible:
+
+```yaml
+
+---
+environment:
+ THEME_LOGO_URL: https://xitaso.com/wp-content/uploads/XITASO-Logo-quer.svg
+```
+
+### Using Azure Entra ID
+
+> **You will need your own AzureAD authentication service!**
+
+You can activate authentication with Azure Entra ID by starting the Mnestix docker container with the
+`-f docker-compose/compose.azure_ad.yml` flag.
+Please configure the tenant ID in both services and both client IDs for your own authentication service in this file.
+
+Use the .env file to configure your sensitive information:
+
+```yaml
+AD_SECRET_VALUE: '<>'
+```
+
+**Note (Mnestix version 1.1.0 and above):** With NextAuth, authentication now happens server-side. You'll need an Azure
+Secret `AD_SECRET_VALUE` for secure server-side communication, unlike the previous client-side SPA setup.
+
+> ⚠️ **Important:** Ensure that you update any confidential variables from their default values before deploying to a
+> production environment.
+
+#### Development
+
+If you want to start the browser with Next.js and Azure authentication directly, take a look at the `.env.local` file
+and update the environment variables mentioned above in there.
+Notably, the following flags must be set `AUTHENTICATION_FEATURE_FLAG: true` and `KEYCLOAK_ENABLED: false`.
+
+### Using the Mnestix Backend
+
+> Without specifying your own API key, Mnestix will use the default 'verySecureApiKey'!
+
+To have the full functionality of the Mnestix Browser you can configure the environment variables for the mnestix-api
+service in the `compose.yml` file.
+It is also necessary to set `MNESTIX_BACKEND_API_KEY`.
+This may be any string and acts as your password for the backend api service and the repo proxy.
+This can be done directly in the `compose.yml` or by defining the environment variable in your `.env` file:
+
+```yaml
+MNESTIX_BACKEND_API_KEY: '<>'
+```
+
+### Retrieval of AAS and Submodels?
+
+#### Concept
+
+The **Discovery Service** enables Mnestix to find all AASs that belong to one Asset.
+We are standard conform but recommend the usage of
+the [BaSyx Implementation of the Discovery Service](https://github.com/eclipse-basyx/basyx-java-server-sdk/tree/main/basyx.aasdiscoveryservice).
+
+The **AAS Registry** is designed to retrieve AAS Descriptors that contain the endpoint for the **Asset Administration
+Shell (AAS) Interface**.
+
+[](https://industrialdigitaltwin.org/wp-content/uploads/2023/07/2023-07-27_IDTA_Tutorial_V3.0-Specification-AAS-Part-2_API.pdf)\
+(
+Source: [IDTA](https://industrialdigitaltwin.org/wp-content/uploads/2023/07/2023-07-27_IDTA_Tutorial_V3.0-Specification-AAS-Part-2_API.pdf))
+
+A tutorial about the Discovery Service along with the registries can be
+found [on the IDTA website](https://industrialdigitaltwin.org/wp-content/uploads/2023/07/2023-07-27_IDTA_Tutorial_V3.0-Specification-AAS-Part-2_API.pdf).
+
+### How to connect Mnestix Browser to the different components
+
+#### Running Mnestix with its API
+
+There also exists the [Mnestix API](https://hub.docker.com/r/mnestix/mnestix-api), that provides different business
+comfort features.
+Here it is possible to set an API Key, for example, to secure your backend services like the repository or the discovery
+service.
+When running the [Mnestix API](https://hub.docker.com/r/mnestix/mnestix-api) you can change the paths to the different
+services like described in the [Mnestix API Documentation](https://hub.docker.com/r/mnestix/mnestix-api).
+For example (change `{{MNESTIX_BACKEND_API_URL}}` to the URL of the
+running [Mnestix API](https://hub.docker.com/r/mnestix/mnestix-api))
+
+```yaml
+DISCOVERY_API_URL: '{{MNESTIX_BACKEND_API_URL}}/discovery'
+AAS_REPO_API_URL: '{{MNESTIX_BACKEND_API_URL}}/repo'
+SUBMODEL_REPO_API_URL: '{{MNESTIX_BACKEND_API_URL}}/repo'
+MNESTIX_BACKEND_API_URL: '{{MNESTIX_BACKEND_API_URL}}'
+```
+
+#### Running Mnestix without its API
+
+This is the easiest configuration, for when you only want to visualize and browse through AAS.
+If you choose to run the Mnestix Browser without the Mnestix API, the Feature Flags `AUTHENTICATION_FEATURE_FLAG`
+and `AAS_LIST_FEATURE_FLAG` will be overwritten to `false` as these Features use the functionality of the API.
+The other environment variables should be configured [as described](#frontend-configuration). If you want to run Mnestix Browser with an Basyx environment you can simply use the compose.frontend file which is described [here](Docker-compose-files).
+
+#### How to configure the BaSyx AAS Repository
+
+We recommend the usage of Mnestix together with
+the [BaSyx AAS Repository](https://github.com/eclipse-basyx/basyx-java-server-sdk).
+This component stores all the different AAS (type 2), it is recommended to configure it to use a database for
+persistence.
+We recommend to set the following environment variables (replace `{{MNESTIX VIEWER URL}}, {{MNESTIX API URL}}` with the
+corresponding values):
+
+```yaml
+# Allow to upload bigger AASX files
+SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE: 100000KB
+SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE: 100000KB
+# Allow mnestix frontend and backend to call basyx
+BASYX_CORS_ALLOWED-ORIGINS: '{{MNESTIX VIEWER URL}}, {{MNESTIX API URL}}'
+BASYX_CORS_ALLOWED-METHODS: GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD
+```
+
+If you are using the Mnestix API see [here](#running-mnestix-with-its-api) on how to set the Frontend Flags.
+If you are using only the Mnestix Browser just set the environment variables `AAS_REPO_API_URL` and
+`SUBMODEL_REPO_API_URL` accordingly.
+
+#### How to configure the BaSyx Discovery Service
+
+We recommend the usage of Mnestix together with
+the [BaSyx AAS Discovery Service](https://github.com/eclipse-basyx/basyx-java-server-sdk/tree/main/basyx.aasdiscoveryservice).
+This component links Asset IDs to AAS IDs. It is recommended to configure it to use a database for persistence.
+We recommend to set the following environment variables (replace `{{MNESTIX VIEWER URL}}, {{MNESTIX API URL}}` with the
+corresponding values):
+
+```yaml
+# Allow mnestix frontend and backend to call discovery service
+BASYX_CORS_ALLOWED-ORIGINS: '{{MNESTIX VIEWER URL}}, {{MNESTIX API URL}}'
+BASYX_CORS_ALLOWED-METHODS: GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD
+```
+
+If you are using the Mnestix API see [here](#running-mnestix-with-its-api) on how to set the Frontend Flags.
+If you are using only the Mnestix Browser just set the environment variable `DISCOVERY_API_URL` accordingly.
+
+#### Technical Information - Discovery Service
+
+The functions that are described in
+the [Specification AAS - Part 2: API](https://industrialdigitaltwin.org/wp-content/uploads/2023/06/IDTA-01002-3-0_SpecificationAssetAdministrationShell_Part2_API_.pdf)
+were implemented in the [`discoveryServiceApi.ts`](src/lib/api/discovery-service-api/discoveryServiceApi.ts).
+They make the respective `GET`, `POST` and `DELETE` requests to the specified `DISCOVERY_API_URL`.
+Two additional functions were added that simplify the usage of the Discovery Service by just requiring the globalAssetId
+and no additional AssetLinks.
+
+These functions are `LinkAasIdAndAssetId(aasId: string, assetId: string)` and `GetAasIdsByAssetId(assetId: string)`.
+The return of all functions is the response from the Discovery Service parsed as an object.
+So they can be used like in the example below:
+
+```typescript
+await LinkAasIdAndAssetId(aasId, assetId);
+const foundAasIds = (await discoveryServiceClient.GetAasIdsByAssetId(assetId)).result;
+```
+
+#### How to configure the BaSyx AAS Registry Service
+
+The AAS Registry Service is designed to provide descriptors for Asset Administration Shells (AAS),
+including endpoints to various repositories that may be stored elsewhere.
+This architecture ensures support for multiple repositories, provided they are registered in the designated AAS
+registry.
+
+When an AAS for the specified AAS-Id is found, it is displayed in the detail view. If the AAS is not found,
+the service will search in the local repository for the requested information.
+
+If the discovery service is configured, it will initially identify the relevant AAS-ID for the searched Asset ID before
+querying the Registry Service.
+Configuration of the Registry Service is optional. If the AAS Registry Service is not configured, the search will
+default to the local repository.
+
+To configure the AAS registry, please provide the URL in the Frontend Configuration variables.
+
+```yaml
+REGISTRY_API_URL: '{{REGISTRY-SERVICE-URL}}'
+```
+
+By setting the REGISTRY_API_URL, you enable the AAS Registry Service, ensuring efficient retrieval of AAS descriptors.
+
+#### How to configure the BaSyx Submodel Registry Service
+
+The Submodel Registry feature provides an optional configuration that allows you to manage and resolve submodels
+efficiently.
+When the Submodel Registry is configured, any reference to a submodel will first check if the submodel is available in
+the specified registry endpoint.
+If the submodel is found in the registry, it will be fetched from there. If the submodel is not found in the registry,
+the system will then check the local repository for the submodel.
+
+Configuring the Submodel Registry is optional. If not configured, all submodel references will default to being resolved
+from the local repository only.
+
+To configure the Submodel registry, please provide the URL in the Frontend Configuration variables.
+
+```yaml
+SUBMODEL_REGISTRY_API_URL: '{{SUBMODEL_REGISTRY_API_URL}}'
+```
+
+By setting the SUBMODEL_REGISTRY_API_URL, you enable the Submodel Registry Service, ensuring efficient retrieval of
+Submodel descriptors.
+
+#### Technical Information - Registry Service
+
+The functions that are described in
+the [Specification AAS - Part 2: API](https://industrialdigitaltwin.org/wp-content/uploads/2023/06/IDTA-01002-3-0_SpecificationAssetAdministrationShell_Part2_API_.pdf)
+were implemented in the [`registryServiceApi.ts`](src/lib/api/registry-service-api/registryServiceApi.ts).
+They make the respective `GET`, `POST` and `DELETE` requests to the specified `REGISTRY_API_URL`.
+
+### Different Mnestix Configurations
+
+There are multiple scenarios possible on how to deploy the Mnestix Browser with different configurations.
+In the following, it is described, what scenarios were thought of and how to configure them
+
+#### I want to only view AAS
+
+If you just want to view AAS and integrate it into your existing environment, you can run only the `mnestix-viewer`
+without its API.
+See [Running Mnestix without its API](#Running-Mnestix-without-its-API).
+
+#### I want to use more advanced features
+
+There are also some more advanced features one might want to use.
+For this you need to enable the Mnestix API, see [here](#running-mnestix-with-its-api).
+It enables you to secure all `POST/PATCH/DELETE`-Request with an API-Key.
+The API-Key needs to be sent within the Header `ApiKey` to make those requests.
+Normal `GET/FETCH`-Requests are not affected by this.
+
+When using it is also possible to restrict some functions that you possibly don't want to be accessible.
+For example, it is possible to restrict the access to the `/shells` endpoint of the AAS repository by setting the
+backend environment variable `Features__AllowRetrievingAllShellsAndSubmodels: false`.
+Remember that this also means that the functionality to list all AAS won't work anymore in the Mnestix Browser, so
+disable this functionality with the environment variable `AAS_LIST_FEATURE_FLAG: false`.
+
+#### AAS List V2 Feature Details
+
+The `AAS_LIST_V2_FEATURE_FLAG` is a feature flag introduced as part of a preview release.
+It enables access to an updated list implementation that operates independently of the Mnestix API.
+
+This flag is currently disabled by default (false) and is available only in preview.
+It is not yet recommended for production environments.
+
+To enable the feature for testing or preview purposes, set the flag to true in your configuration.
+
+#### AzureAD Service
+
+One can also add an AzureAD Service to give people deeper access, this enables the "Login" Button in the Mnestix
+Browser.
+After logging in, users have access to even more functionality.
+To see how to connect to an Azure Tenant and enable the login functionality see
+the [official Mnestix API documentation](https://hub.docker.com/r/mnestix/mnestix-api).
+
+#### I want to create multiple AAS
+
+This option builds upon the advanced features described in
+the [previous section](#i-want-to-use-more-advanced-features).
+After logging in it is possible to configure the ID Generation Functionality of the backend.
+Here it is possible to automatically generate AAS using only a short ID of the Asset.
+How the AAS Creator in conjunction with the ID Generations Functionality works can be seen in
+the [official Mnestix API documentation](https://hub.docker.com/r/mnestix/mnestix-api).
+
+One can also use the Template Builder with the Data Ingest Endpoint to send arbitrary JSON files to the API and
+automatically add them to a specified AAS.
+This enables easy integration into existing ETL processes.
+How exactly this works can be seen in
+the [official Mnestix API documentation](https://hub.docker.com/r/mnestix/mnestix-api).
+
+Below you'll find a small overview on how the components interact with each other:
+![Overview of all Mnestix Functionality](https://xitaso.com/wp-content/uploads/final_LP_Desktop_Mnestix_AAS_0424_cor.svg)
\ No newline at end of file
diff --git a/wiki/Secret-Environment-Variables.md b/wiki/Secret-Environment-Variables.md
new file mode 100644
index 00000000..4a6701aa
--- /dev/null
+++ b/wiki/Secret-Environment-Variables.md
@@ -0,0 +1,13 @@
+You can (and should) create your personal `.env` file in the root directory.
+Simply rename `.env.example` to `.env` and enter your secrets.
+The secrets may be arbitrary strings.
+
+This `.env` file will be used automatically by docker compose and Next.js.
+
+```yaml
+AD_SECRET_VALUE: '<>'
+MNESTIX_BACKEND_API_KEY: '<>'
+NEXTAUTH_SECRET: '<>'
+```
+
+> ⚠️ **Important:** If you have not configured these secrets, a public secret will be used as a fallback!
\ No newline at end of file
diff --git a/wiki/Use-Mnestix.md b/wiki/Use-Mnestix.md
new file mode 100644
index 00000000..e9c48107
--- /dev/null
+++ b/wiki/Use-Mnestix.md
@@ -0,0 +1,22 @@
+### Upload your first AAS
+
+We provide a simple AAS in the folder **test-data** which you can use as a first test AAS.
+You can upload the `.aasx` file to your BaSyx repository by using the upload endpoint of BaSyx (check
+`http://localhost:8081/swagger-ui/index.html` and search for the `/upload` endpoint to get more information).
+Afterward, you can visit your running Mnestix Browser and search for the AAS ID `https://vws.xitaso.com/aas/mnestix` to
+visualize the test AAS.
+
+### Personalization
+
+It is possible to change the look and feel by setting a theme color and a personal logo when deploying the Mnestix
+Browser, see [here](https://github.com/eclipse-mnestix/mnestix-browser/wiki/Mnestix-Configuration-Settings#how-to-set-a-custom-logo).
+
+### BaSyx API
+
+- Mnestix is using BaSyx, by appending /repo to our URLs, we are forwarding the requests to BaSyx via
+ proxy: [BaSyx AAS API Collection](https://app.swaggerhub.com/apis/Plattform_i40/Entire-API-Collection/V3.0#/Asset%20Administration%20Shell%20Repository%20API/GetAssetAdministrationShellById)
+- With this, BaSyx endpoints can be reached through Mnestix.
+ - AAS Repository Api: http://localhost:3000/repo/shells/{YourAasIdInBase64}
+ - Submodel Repository Api: http://localhost:3000/repo/submodels/{YourAasIdInBase64}
+ - The BaSyx Swagger UI gives a detailed overview of all available
+ endpoints: http://localhost:8081/swagger-ui/index.html
\ No newline at end of file
diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md
new file mode 100644
index 00000000..baded2c5
--- /dev/null
+++ b/wiki/_Sidebar.md
@@ -0,0 +1,27 @@
+# Main
+
+- [Home](Home)
+- [Feature Overview](Feature-Overview)
+
+## Getting Started
+
+- [Use Mnestix](Use-Mnestix)
+- [Getting Started with Developing](Getting-started-with-developing)
+
+## Configuration
+
+- [Mnestix Configuration Settings](Mnestix-Configuration-Settings)
+- [Secret Environment Variables](Secret-environment-variables)
+- [Docker Compose Files](Docker-Compose-Files)
+- [Keycloak Configuration](Keycloak-Configuration)
+- [Maintaining](Maintaining)
+
+## Contribution
+
+- [Contributing](Contributing)
+
+## Advanced
+
+- [How to Create Custom Submodel Views](How-to-create-custom-submodel-visualizations)
+
+
\ No newline at end of file
From 25b316b14ba2c8fabdf01d4559fb698195ff2af7 Mon Sep 17 00:00:00 2001
From: NilsXitaso
Date: Thu, 6 Feb 2025 09:20:28 +0100
Subject: [PATCH 19/23] Chore(submodel tooltip):rework the tooltip (#92)
* Add translation to the error tooltip messages
* Add translation to the error tooltip messages
* Add translation to the error tooltip messages
* fix locale file
---------
Co-authored-by: melanie.gail
---
.../_components/SubmodelsOverviewCard.tsx | 2 +-
src/components/basics/VerticalTabSelector.tsx | 92 +++++++++++--------
src/locale/de.json | 8 +-
src/locale/en.json | 8 +-
4 files changed, 67 insertions(+), 43 deletions(-)
diff --git a/src/app/[locale]/viewer/_components/SubmodelsOverviewCard.tsx b/src/app/[locale]/viewer/_components/SubmodelsOverviewCard.tsx
index 2b191e69..672d1db7 100644
--- a/src/app/[locale]/viewer/_components/SubmodelsOverviewCard.tsx
+++ b/src/app/[locale]/viewer/_components/SubmodelsOverviewCard.tsx
@@ -51,7 +51,7 @@ export function SubmodelsOverviewCard({ submodelIds, submodelsLoading }: Submode
id: submodelId.id,
label: submodelId.id,
startIcon: ,
- submodelError: submodelId.error ?? ''
+ submodelError: submodelId.error ?? 'UNKNOWN'
};
}
}
diff --git a/src/components/basics/VerticalTabSelector.tsx b/src/components/basics/VerticalTabSelector.tsx
index 1bd9dadd..e87de385 100644
--- a/src/components/basics/VerticalTabSelector.tsx
+++ b/src/components/basics/VerticalTabSelector.tsx
@@ -4,6 +4,7 @@ import { ReactElement, useState } from 'react';
import { Submodel } from '@aas-core-works/aas-core3.0-typescript/types';
import { tooltipText } from 'lib/util/ToolTipText';
import { SubmodelInfoDialog } from 'app/[locale]/viewer/_components/submodel/SubmodelInfoDialog';
+import { useTranslations } from 'next-intl';
export type TabSelectorItem = {
readonly id: string;
@@ -60,58 +61,70 @@ const Tab = styled(Button)(({ theme }) => ({
export function VerticalTabSelector(props: VerticalTabSelectorProps) {
const [submodelInfoDialogOpen, setSubmodelInfoDialogOpen] = useState(false);
const [hoveredItem, setHoveredItem] = useState();
+ const t = useTranslations('submodels.errors');
+ type message = 'NOT_FOUND'|'UNAUTHORIZED'|'INTERNAL_SERVER_ERROR'|'UNKNOWN';
const selectedCSSClass = (id: string) => (id === props.selected?.id ? 'selected' : '');
const handleSubmodelInfoModalClose = () => {
- setHoveredItem(undefined)
+ setHoveredItem(undefined);
setSubmodelInfoDialogOpen(false);
- }
+ };
return (
- setHoveredItem(undefined)}
+ setHoveredItem(undefined)}
>
{props.items.map((item, index) => {
return (
- setHoveredItem(item)}>
- props.setSelected && props.setSelected(item)}
- className={`tab-item ${selectedCSSClass(item.id)}`}
- disabled={!!item.submodelError}
- >
-
- {tooltipText(item.label, 40) || ''}
-
+ setHoveredItem(item)}>
+ props.setSelected && props.setSelected(item)}
+ className={`tab-item ${selectedCSSClass(item.id)}`}
+ disabled={!!item.submodelError}
+ >
+
+ {tooltipText(item.label, 40) || ''}
+
-
-
- {item.submodelError ? (
-
-
- {item.startIcon}
-
-
- ) : (
-
- {
- setSubmodelInfoDialogOpen(true);
- event.stopPropagation(); // don't open the tab
- }}>
+
+
+ {item.submodelError ? (
+
+
+ {item.startIcon}
+
+
+ ) : (
+
+ {
+ setSubmodelInfoDialogOpen(true);
+ event.stopPropagation(); // don't open the tab
+ }}
+ >
{item.startIcon}
-
-
- )}
+
+
+ )}
+
+
-
-
-
+
);
})}
@@ -122,6 +135,5 @@ export function VerticalTabSelector(props: VerticalTabSelectorProps) {
idShort={hoveredItem?.submodelData?.idShort}
/>
-
);
}
diff --git a/src/locale/de.json b/src/locale/de.json
index f3222ca0..057c07dc 100644
--- a/src/locale/de.json
+++ b/src/locale/de.json
@@ -37,7 +37,13 @@
},
"renderError": "Teilmodell konnte nicht gerendert werden.",
"idLabel": "ID:",
- "unknownModelType": "Unbekannter ModelType: {type}"
+ "unknownModelType": "Unbekannter ModelType: {type}",
+ "errors": {
+ "NOT_FOUND": "Submodel nicht gefunden",
+ "UNAUTHORIZED": "Nicht autorisiert",
+ "INTERNAL_SERVER_ERROR": "Interner Server Error",
+ "UNKNOWN": "Unbekannter Fehler"
+ }
},
"qr-scanner": {
"errors": {
diff --git a/src/locale/en.json b/src/locale/en.json
index 89faa1c7..0eaa688e 100644
--- a/src/locale/en.json
+++ b/src/locale/en.json
@@ -37,7 +37,13 @@
},
"renderError": "Submodel can't be rendered.",
"idLabel": "ID:",
- "unknownModelType": "Unknown ModelType: {type}"
+ "unknownModelType": "Unknown ModelType: {type}",
+ "errors": {
+ "NOT_FOUND": "Submodel not found",
+ "UNAUTHORIZED": "Unauthorized",
+ "INTERNAL_SERVER_ERROR": "Internal server error",
+ "UNKNOWN": "Unknown Error"
+ }
},
"qr-scanner": {
"errors": {
From b51d062cd6bd9d69011723bcb0a43b8c105e4fdb Mon Sep 17 00:00:00 2001
From: Melanie Gail
Date: Thu, 6 Feb 2025 11:06:20 +0100
Subject: [PATCH 20/23] wiki update (#93)
---
wiki/Keycloak-Configuration.md | 6 ++++--
wiki/Mnestix-Configuration-Settings.md | 11 +++++++----
wiki/Role-Based-Access-Control.md | 22 ++++++++++++++++++++++
wiki/_Sidebar.md | 5 +++--
4 files changed, 36 insertions(+), 8 deletions(-)
create mode 100644 wiki/Role-Based-Access-Control.md
diff --git a/wiki/Keycloak-Configuration.md b/wiki/Keycloak-Configuration.md
index e771a953..e8bec983 100644
--- a/wiki/Keycloak-Configuration.md
+++ b/wiki/Keycloak-Configuration.md
@@ -25,7 +25,7 @@ eliminating the need for any initial Keycloak configuration.
The Keycloak Admin Console will be accessible at [http://localhost:8080/admin](http://localhost:8080/admin).
-For initial access, use the following temporary credentials:
+For initial access of the Keycloak Admin Console, use the following temporary credentials:
- **Username:** admin
- **Password:** admin
@@ -33,7 +33,9 @@ For initial access, use the following temporary credentials:
A test user is preconfigured with the following credentials allowing login to Mnestix Browser:
- **Username:** test
-- **Password:** test
+- **Password:** test
+ The role mnestix-admin is assigned to this test user by default. More information regarding Role Based Access Control
+ can be found [here](Role-Based-Access-Control)
### Configuration Variables for Keycloak Setup
diff --git a/wiki/Mnestix-Configuration-Settings.md b/wiki/Mnestix-Configuration-Settings.md
index 2b93135f..09b22f24 100644
--- a/wiki/Mnestix-Configuration-Settings.md
+++ b/wiki/Mnestix-Configuration-Settings.md
@@ -11,7 +11,6 @@ Mnestix provides the following configuration options. You can adapt the values i
| `SUBMODEL_REPO_API_URL` | | Default Submodel Repository to display when Submodel Id is not in Submodel Registry | required |
| `MNESTIX_BACKEND_API_URL` | | Mnestix Backend with a lot of business comfort features like the Repository-Proxy or the Template builder | optional |
| `AAS_LIST_FEATURE_FLAG` | false | Enables or disables the AasList in the frontend. This only works in combination with `Features__AllowRetrievingAllShellsAndSubmodels` being set to `true` (Needs the Mnestix Backend to work) | optional |
-| `AAS_LIST_V2_FEATURE_FLAG` | false | The functionality controlled by this flag is under active development and may change without notice. Please see [details](#aas-list-v2-feature-details) | optional |
| `TRANSFER_FEATURE_FLAG` | false | Enables or disables the Transfer Feature in the frontend. If enabled, it is possible to import a viewed AAS to a configured repository. This feature is currently being developed. | optional |
| `AUTHENTICATION_FEATURE_FLAG` | false | Enable or disable the authentication in the frontend. (Needs the Mnestix Backend to work) | optional |
| `COMPARISON_FEATURE_FLAG` | false | Enables or disables the comparison feature. | optional |
@@ -44,8 +43,10 @@ volumes:
- /path/to/my/logo.svg:/app/public/logo
```
-When using the provided [`compose.yaml` File](https://github.com/eclipse-mnestix/mnestix-browser/blob/main/compose.yml) you can just replace the [image in the
-`data` folder](https://github.com/eclipse-mnestix/mnestix-browser/tree/main/docker-compose/data/logo.svg) with your preferred logo.
+When using the provided [`compose.yaml` File](https://github.com/eclipse-mnestix/mnestix-browser/blob/main/compose.yml)
+you can just replace the [image in the
+`data` folder](https://github.com/eclipse-mnestix/mnestix-browser/tree/main/docker-compose/data/logo.svg) with your
+preferred logo.
Remember to set the mime type correctly in order for the browser to parse your image correctly.
Only image mime types are allowed.
@@ -146,7 +147,9 @@ MNESTIX_BACKEND_API_URL: '{{MNESTIX_BACKEND_API_URL}}'
This is the easiest configuration, for when you only want to visualize and browse through AAS.
If you choose to run the Mnestix Browser without the Mnestix API, the Feature Flags `AUTHENTICATION_FEATURE_FLAG`
and `AAS_LIST_FEATURE_FLAG` will be overwritten to `false` as these Features use the functionality of the API.
-The other environment variables should be configured [as described](#frontend-configuration). If you want to run Mnestix Browser with an Basyx environment you can simply use the compose.frontend file which is described [here](Docker-compose-files).
+The other environment variables should be configured [as described](#frontend-configuration). If you want to run Mnestix
+Browser with an Basyx environment you can simply use the compose.frontend file which is
+described [here](Docker-compose-files).
#### How to configure the BaSyx AAS Repository
diff --git a/wiki/Role-Based-Access-Control.md b/wiki/Role-Based-Access-Control.md
new file mode 100644
index 00000000..f777a0c0
--- /dev/null
+++ b/wiki/Role-Based-Access-Control.md
@@ -0,0 +1,22 @@
+### Role Based Access Control
+
+Mnestix currently uses a basic RBAC approach when `AUTHENTICATION_FEATURE_FLAG` is set to `true`.
+
+A not logged-in user is allowed to see the following pages with all features:
+
+- Dashboard, List
+
+Every logged-in user is allowed to visit following pages:
+
+- Dashboard, List, Templates
+
+If a logged-in user has the mnestix-admin role set, the user is able to visit following pages:
+
+- Dashboard, List, Templates, Settings (ID Settings, Data Sources)
+
+### Configuring RBAC:
+
+Since we support Keycloak and Azure Entra ID as authentication providers, you are able to configure mnestix roles in
+both of them.
+To do so, create the role `mnestix-admin` in either Keycloak or Azure Entra ID and assign it to a chosen user.
+Nothing needs to be configured inside Mnestix.
\ No newline at end of file
diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md
index baded2c5..23f84eb9 100644
--- a/wiki/_Sidebar.md
+++ b/wiki/_Sidebar.md
@@ -15,6 +15,7 @@
- [Docker Compose Files](Docker-Compose-Files)
- [Keycloak Configuration](Keycloak-Configuration)
- [Maintaining](Maintaining)
+- [Role Based Access Control](Role-Based-Access-Control)
## Contribution
@@ -23,5 +24,5 @@
## Advanced
- [How to Create Custom Submodel Views](How-to-create-custom-submodel-visualizations)
-
-
\ No newline at end of file
+
+
\ No newline at end of file
From 6eed7ec209d905f19afe9c200ea9b865d3e63526 Mon Sep 17 00:00:00 2001
From: Melanie Gail
Date: Thu, 6 Feb 2025 11:16:06 +0100
Subject: [PATCH 21/23] fix dialog when mouse leaves the page (#94)
---
src/components/basics/VerticalTabSelector.tsx | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/components/basics/VerticalTabSelector.tsx b/src/components/basics/VerticalTabSelector.tsx
index e87de385..62fdce65 100644
--- a/src/components/basics/VerticalTabSelector.tsx
+++ b/src/components/basics/VerticalTabSelector.tsx
@@ -61,8 +61,9 @@ const Tab = styled(Button)(({ theme }) => ({
export function VerticalTabSelector(props: VerticalTabSelectorProps) {
const [submodelInfoDialogOpen, setSubmodelInfoDialogOpen] = useState(false);
const [hoveredItem, setHoveredItem] = useState();
+ const [dialogItem, setDialogItem] = useState();
const t = useTranslations('submodels.errors');
- type message = 'NOT_FOUND'|'UNAUTHORIZED'|'INTERNAL_SERVER_ERROR'|'UNKNOWN';
+ type message = 'NOT_FOUND' | 'UNAUTHORIZED' | 'INTERNAL_SERVER_ERROR' | 'UNKNOWN';
const selectedCSSClass = (id: string) => (id === props.selected?.id ? 'selected' : '');
@@ -113,6 +114,7 @@ export function VerticalTabSelector(props: VerticalTabSelectorProps) {
display="flex"
sx={{ cursor: 'pointer' }}
onClick={(event) => {
+ setDialogItem(hoveredItem);
setSubmodelInfoDialogOpen(true);
event.stopPropagation(); // don't open the tab
}}
@@ -131,8 +133,8 @@ export function VerticalTabSelector(props: VerticalTabSelectorProps) {
);
From fa2def074fe08bdaa3453162de01890bb8369126 Mon Sep 17 00:00:00 2001
From: Melanie Gail
Date: Thu, 6 Feb 2025 11:57:07 +0100
Subject: [PATCH 22/23] increase version to 1.4.0 (#95)
---
.github/workflows/docker-build.yml | 2 +-
compose.yml | 2 +-
package.json | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml
index e23396da..01203d6e 100644
--- a/.github/workflows/docker-build.yml
+++ b/.github/workflows/docker-build.yml
@@ -16,7 +16,7 @@ env:
IMAGE_NAME: mnestix-browser
IMAGE_TAG: latest
# Update the version manually
- IMAGE_TAG_VERSION: 1.3.3
+ IMAGE_TAG_VERSION: 1.4.0
REGISTRY_USER: ${{ secrets.DOCKER_USERNAME }}
REGISTRY_PASS: ${{ secrets.DOCKER_API_TOKEN }}
diff --git a/compose.yml b/compose.yml
index f409d6e7..398e2ad7 100644
--- a/compose.yml
+++ b/compose.yml
@@ -41,7 +41,7 @@ services:
- mnestix-database:/app/prisma/database
mnestix-api:
- image: mnestix/mnestix-api:1.2.5
+ image: mnestix/mnestix-api:1.3.0
container_name: mnestix-api
profiles: [ "", "backend", "tests" ]
ports:
diff --git a/package.json b/package.json
index 1f624dfc..a0bac0f7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "mnestix-browser",
- "version": "1.3.3",
+ "version": "1.4.0",
"private": true,
"license": "MIT",
"devDependencies": {
From 2cb7dc066cad2c1d222458bd7f9ebbfa03e2e558 Mon Sep 17 00:00:00 2001
From: "melanie.gail"
Date: Thu, 6 Feb 2025 15:28:37 +0100
Subject: [PATCH 23/23] fix show user name when logged in with entra id
---
src/components/authentication/authConfig.ts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/components/authentication/authConfig.ts b/src/components/authentication/authConfig.ts
index 3254d2c5..89cc2c96 100644
--- a/src/components/authentication/authConfig.ts
+++ b/src/components/authentication/authConfig.ts
@@ -64,9 +64,11 @@ export const authOptions: AuthOptions = {
if (account.id_token) {
const decodedToken = jwt.decode(account.id_token);
if (decodedToken) {
- if (account.provider === 'azure-ad') {
+ if (account.provider === 'azure-ad' && account.access_token) {
+ // Entra ID stores the username only in the access_token
+ const decodedAccessToken = jwt.decode(account.access_token);
// @ts-expect-error name exits
- userName = decodedToken.name;
+ userName = decodedAccessToken.name;
}
// @ts-expect-error role exits
roles = decodedToken.roles;