diff --git a/src/assets/locales/de/main.json b/src/assets/locales/de/main.json index d144d427b8..79e7cda921 100644 --- a/src/assets/locales/de/main.json +++ b/src/assets/locales/de/main.json @@ -2369,6 +2369,10 @@ "title": "Assigned Catena-X Portal Roles", "changeRoleBtn": "Change Portal Role", "errorMsg": "Sie sind nicht berechtigt, Ihre eigenen Administrator-Rollen zu ändern. Bitte wenden Sie sich an einen anderen Administrator." + }, + "table": { + "emptySearchTable": "Keine Ergebnisse gefunden", + "emptyTable": "Keine Einträge vorhanden" } }, "global": { diff --git a/src/assets/locales/en/main.json b/src/assets/locales/en/main.json index 765bfc6874..10cb000b43 100644 --- a/src/assets/locales/en/main.json +++ b/src/assets/locales/en/main.json @@ -2369,6 +2369,10 @@ "title": "Assigned Catena-X Portal Roles", "changeRoleBtn": "Change Portal Role", "errorMsg": "You are not authorized to change your own admin roles. Please contact another admin." + }, + "table": { + "emptySearchTable": "No results found", + "emptyTable": "No items to display" } }, "global": { diff --git a/src/components/overlays/AddAppUserRoles/UserListContent.tsx b/src/components/overlays/AddAppUserRoles/UserListContent.tsx index 0d9b0297f0..3c9574d2be 100644 --- a/src/components/overlays/AddAppUserRoles/UserListContent.tsx +++ b/src/components/overlays/AddAppUserRoles/UserListContent.tsx @@ -30,6 +30,7 @@ import { updatePartnerSelector } from 'features/control/updates' import { setSelectedUserToAdd } from 'features/admin/userDeprecated/slice' import Patterns from 'types/Patterns' import { useFetchAppUsersSearchQuery } from 'features/admin/appuserApiSlice' +import { PAGES } from 'types/Constants' interface FetchHookArgsType { appId: string | undefined @@ -42,6 +43,10 @@ export default function UserListContent() { const dispatch = useDispatch() const { appId } = useParams() + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const [expr, setExpr] = useState('') const [refresh, setRefresh] = useState(0) @@ -94,6 +99,7 @@ export default function UserListContent() { }, ]} checkboxSelection + mappedTableSearchTranslation={mappedTableSearchTranslation} /> ) } diff --git a/src/components/pages/Admin/RegistrationRequests/RequestList/index.tsx b/src/components/pages/Admin/RegistrationRequests/RequestList/index.tsx index ff01c0288f..ddb9612377 100644 --- a/src/components/pages/Admin/RegistrationRequests/RequestList/index.tsx +++ b/src/components/pages/Admin/RegistrationRequests/RequestList/index.tsx @@ -36,6 +36,7 @@ import { type GridEventListener } from '@mui/x-data-grid' import './style.scss' import { refetch } from 'features/admin/registration/slice' import { isCompanyName } from 'types/Patterns' +import { PAGES } from 'types/Constants' interface FetchHookArgsType { statusFilter: string @@ -65,6 +66,10 @@ export const RequestList = ({ const [filterStatus, setFilterStatus] = useState( AppFilterType.INREVIEW ) + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const [fetchHookArgs, setFetchHookArgs] = useState() const setView = (e: React.MouseEvent) => { const viewValue = e.currentTarget.value @@ -154,6 +159,7 @@ export const RequestList = ({ )}${t('content.admin.registration-requests.introText2')}`} defaultFilter={group} filterViews={filterView} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> ) diff --git a/src/components/pages/AdminCredential/AdminCredentialElements.tsx b/src/components/pages/AdminCredential/AdminCredentialElements.tsx index d7a9c1b5f8..0be1e6372c 100644 --- a/src/components/pages/AdminCredential/AdminCredentialElements.tsx +++ b/src/components/pages/AdminCredential/AdminCredentialElements.tsx @@ -48,7 +48,7 @@ import { StatusTag, Tooltips, } from '@catena-x/portal-shared-components' -import { ROLES } from 'types/Constants' +import { PAGES, ROLES } from 'types/Constants' import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore' import { userHasSsiCredentialRole } from 'services/AccessService' @@ -97,6 +97,10 @@ export default function AdminCredentialElements() { const [approveCredential] = useApproveCredentialMutation() const [declineCredential] = useDeclineCredentialMutation() const [revokeCredential] = useRevokeCredentialMutation() + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const setView = (e: React.MouseEvent) => { const viewValue = e.currentTarget.value @@ -436,6 +440,7 @@ export default function AdminCredentialElements() { setSortOption(value) }} disableColumnSelector={true} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> diff --git a/src/components/pages/AppOverview/AddRoles.tsx b/src/components/pages/AppOverview/AddRoles.tsx index 2cb62b6cf1..11adc3edb5 100644 --- a/src/components/pages/AppOverview/AddRoles.tsx +++ b/src/components/pages/AppOverview/AddRoles.tsx @@ -194,6 +194,7 @@ export default function AddRoles() { rows={appRolesData} getRowId={(row) => uniqueId(row.urn)} hasBorder={false} + noRowsMsg={t('shared.table.emptyTable')} /> diff --git a/src/components/pages/CompanyData/CompanyAddressList.tsx b/src/components/pages/CompanyData/CompanyAddressList.tsx index 5b9e0754f9..7a0f78beaf 100644 --- a/src/components/pages/CompanyData/CompanyAddressList.tsx +++ b/src/components/pages/CompanyData/CompanyAddressList.tsx @@ -213,7 +213,7 @@ export const CompanyAddressList = ({ searchDebounce={1000} noRowsMsg={ !isFetching && !isOutputLoading && !isInputLoading - ? t('content.companyData.table.noRowsMsg') + ? t('shared.table.emptyTable') : '' } title={t('content.companyData.table.title')} diff --git a/src/components/pages/CompanySubscriptions/index.tsx b/src/components/pages/CompanySubscriptions/index.tsx index d914877fd9..d296bd4fe4 100644 --- a/src/components/pages/CompanySubscriptions/index.tsx +++ b/src/components/pages/CompanySubscriptions/index.tsx @@ -47,6 +47,7 @@ import { } from 'features/serviceSubscription/serviceSubscriptionApiSlice' import { Box } from '@mui/material' import { useLocation } from 'react-router-dom' +import { PAGES } from 'types/Constants' interface FetchHookArgsType { statusId: string @@ -79,6 +80,11 @@ export default function CompanySubscriptions() { location.state?.activeTab ?? 0 ) + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } + const setView = (e: React.MouseEvent) => { const viewValue = e.currentTarget.value setFilterStatus(viewValue) @@ -229,6 +235,7 @@ export default function CompanySubscriptions() { onClearSearch={() => { setSearchExpr('') }} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> ) diff --git a/src/components/pages/EdcConnector/index.tsx b/src/components/pages/EdcConnector/index.tsx index 32e9521df2..3910f27651 100644 --- a/src/components/pages/EdcConnector/index.tsx +++ b/src/components/pages/EdcConnector/index.tsx @@ -67,6 +67,7 @@ import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline' import ArrowForwardIcon from '@mui/icons-material/ArrowForward' import { Box } from '@mui/material' import { ProvidedConnectorTableColumns } from './edcProvidedConnectorTableColumns' +import { PAGES } from 'types/Constants' const EdcConnector = () => { const { t } = useTranslation() @@ -109,6 +110,10 @@ const EdcConnector = () => { const [notificationMessage, setNotificationMessage] = useState( t('content.edcconnector.snackbar.successmessage') ) + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const [ viewConfigurationDetailsOverlayOpen, setViewConfigurationDetailsOverlayOpen, @@ -504,6 +509,7 @@ const EdcConnector = () => { onCellClick={(params: GridCellParams) => { onTableCellClick(params) }} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> @@ -521,6 +527,7 @@ const EdcConnector = () => { onCellClick={(params: GridCellParams) => { onTableCellClick(params) }} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> diff --git a/src/components/pages/IDPManagement/IDPList.tsx b/src/components/pages/IDPManagement/IDPList.tsx index 0a0d19fa67..cd4d1e2baf 100644 --- a/src/components/pages/IDPManagement/IDPList.tsx +++ b/src/components/pages/IDPManagement/IDPList.tsx @@ -18,7 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useDispatch } from 'react-redux' import { useTranslation } from 'react-i18next' import { MenuItem } from '@mui/material' @@ -394,6 +394,17 @@ export const IDPList = ({ isManagementOSP }: { isManagementOSP?: boolean }) => { ) } + const rowItems = (isManagementOSP ? idpsManagedData : idpsData) ?? [] + + const getNoRowsMessage = useMemo(() => { + if (!rowItems.length) { + return searchExpr + ? t('shared.table.emptySearchTable') + : t('shared.table.emptyTable') + } + return '' + }, [rowItems, searchExpr, t]) + return ( { disableColumnSelector={true} disableDensitySelector={true} columnHeadersBackgroundColor={'#ffffff'} + rows={rowItems} title={ isManagementOSP ? t('content.onboardingServiceProvider.ospIdentityProvider') @@ -471,7 +483,6 @@ export const IDPList = ({ isManagementOSP }: { isManagementOSP?: boolean }) => { isManagementOSP ? renderManagementOSPMenu(row) : renderMenu(row), }, ]} - rows={(isManagementOSP ? idpsManagedData : idpsData) ?? []} getRowId={(row: { [key: string]: string }) => row.identityProviderId} hasBorder={false} searchPlaceholder={ @@ -491,6 +502,7 @@ export const IDPList = ({ isManagementOSP }: { isManagementOSP?: boolean }) => { searchDebounce={isManagementOSP ? 1000 : undefined} onButtonClick={() => dispatch(show(OVERLAYS.ADD_IDP))} buttonLabel={t('content.onboardingServiceProvider.addIdentityProvider')} + noRowsMsg={getNoRowsMessage} sx={{ '.MuiDataGrid-cell': { display: 'flex', diff --git a/src/components/pages/InviteBusinessPartner/InviteList/index.tsx b/src/components/pages/InviteBusinessPartner/InviteList/index.tsx index 70e3762580..33d7ac8bd4 100644 --- a/src/components/pages/InviteBusinessPartner/InviteList/index.tsx +++ b/src/components/pages/InviteBusinessPartner/InviteList/index.tsx @@ -33,6 +33,7 @@ import dayjs from 'dayjs' import { setSearchInput } from 'features/appManagement/actions' import { updateInviteSelector } from 'features/control/updates' import { isCompanyName } from 'types/Patterns' +import { PAGES } from 'types/Constants' interface FetchHookArgsType { expr: string @@ -57,6 +58,10 @@ export const InviteList = ({ const dispatch = useDispatch() const [refresh, setRefresh] = useState(0) const searchInputData = useSelector(updateInviteSelector) + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const validateSearchText = (expr: string) => { const validateExpr = isCompanyName(expr) @@ -135,6 +140,7 @@ export const InviteList = ({ ), }, ]} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> ) diff --git a/src/components/pages/OnboardingServiceProvider/OnboardingServiceProvider.tsx b/src/components/pages/OnboardingServiceProvider/OnboardingServiceProvider.tsx index 6b979229ce..421ec60f05 100644 --- a/src/components/pages/OnboardingServiceProvider/OnboardingServiceProvider.tsx +++ b/src/components/pages/OnboardingServiceProvider/OnboardingServiceProvider.tsx @@ -50,6 +50,7 @@ import { isIDPClientID, isIDPClientSecret, isURL } from 'types/Patterns' import { type IHashMap } from 'types/MainTypes' import { success } from 'services/NotifyService' import WarningAmberIcon from '@mui/icons-material/WarningAmber' +import { PAGES } from 'types/Constants' const OnboardingServiceProvider = () => { const { t } = useTranslation() @@ -64,6 +65,10 @@ const OnboardingServiceProvider = () => { const [callbackData, setCallbackData] = useState< RegistartionStatusCallbackType | undefined >(undefined) + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const handleTabChange = ( _e: SyntheticEvent, @@ -404,6 +409,7 @@ const OnboardingServiceProvider = () => { sortable: false, }, ]} + mappedTableSearchTranslation={mappedTableSearchTranslation} /> diff --git a/src/components/pages/PartnerNetwork/index.tsx b/src/components/pages/PartnerNetwork/index.tsx index 7b13af8562..f30b7eafd6 100644 --- a/src/components/pages/PartnerNetwork/index.tsx +++ b/src/components/pages/PartnerNetwork/index.tsx @@ -30,7 +30,7 @@ import { type PaginResult, } from '@catena-x/portal-shared-components' import { useSelector } from 'react-redux' -import { useEffect, useState } from 'react' +import { useEffect, useState, useMemo } from 'react' import { updatePartnerSelector } from 'features/control/updates' import { PartnerNetworksTableColumns } from 'components/pages/PartnerNetwork/partnerNetworkTableColumns' import type { BusinessPartner } from 'features/newPartnerNetwork/types' @@ -134,6 +134,15 @@ const PartnerNetwork = () => { fetchAndApply([bpn]) }, [bpn]) + const getNoRowsMessage = useMemo(() => { + if (!allItems.length) { + return expr || bpn + ? t('shared.table.emptySearchTable') + : t('shared.table.emptyTable') + } + return '' + }, [allItems, expr, bpn, t]) + return (
{ loading={loading} rows={allItems} rowsCount={allItems?.length} - noRowsMsg={t('content.companyData.table.noRowsMsg')} nextPage={() => { setPage(page + 1) }} @@ -180,6 +188,7 @@ const PartnerNetwork = () => { memberData.meta.page < memberData.meta.totalPages - 1 } hideFooterPagination={true} + noRowsMsg={getNoRowsMessage} />
diff --git a/src/components/pages/SemanticHub/ModelTable.tsx b/src/components/pages/SemanticHub/ModelTable.tsx index e52ec5d6fe..93890cfd72 100644 --- a/src/components/pages/SemanticHub/ModelTable.tsx +++ b/src/components/pages/SemanticHub/ModelTable.tsx @@ -27,7 +27,7 @@ import { type SemanticModel, DefaultStatus, } from 'features/semanticModels/types' -import { useState, useEffect } from 'react' +import { useState, useEffect, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { LoadMoreButton } from '../../shared/basic/LoadMoreButton' import { SemanticModelTableColumns } from './SemanticModelTableColumn' @@ -152,6 +152,15 @@ const ModelTable = ({ onModelSelect }: ModelTableProps) => { : t('global.errors.loadFailed') } + const getNoRowsMessage = useMemo(() => { + if (!models.length) { + return searchValue + ? t('shared.table.emptySearchTable') + : t('shared.table.emptyTable') + } + return '' + }, [models, searchValue, t]) + return (
{ reload={() => { setPageNumber(0) }} - noRowsMsg={t('global.noData.heading')} + noRowsMsg={getNoRowsMessage} />
{modelList?.totalPages !== pageNumber && ( diff --git a/src/components/pages/TechnicalUserManagement/TechnicalUserTable.tsx b/src/components/pages/TechnicalUserManagement/TechnicalUserTable.tsx index 823664fe90..a0b497209b 100644 --- a/src/components/pages/TechnicalUserManagement/TechnicalUserTable.tsx +++ b/src/components/pages/TechnicalUserManagement/TechnicalUserTable.tsx @@ -20,8 +20,8 @@ import { IconButton, - PageLoadingTable, StatusTag, + PageLoadingTable, } from '@catena-x/portal-shared-components' import { useTranslation } from 'react-i18next' import ArrowForwardIcon from '@mui/icons-material/ArrowForward' @@ -54,6 +54,12 @@ export const TechnicalUserTable = () => { const [group, setGroup] = useState( ServiceAccountStatusFilter.SHOW_ALL ) + + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } + const setView = (e: React.MouseEvent) => { const viewValue = e.currentTarget.value setGroup(viewValue) @@ -208,6 +214,7 @@ export const TechnicalUserTable = () => { ), }, ]} + mappedTableSearchTranslation={mappedTableSearchTranslation} />
) diff --git a/src/components/shared/frame/UserList/index.tsx b/src/components/shared/frame/UserList/index.tsx index 5428bb57c9..4a42c52e93 100644 --- a/src/components/shared/frame/UserList/index.tsx +++ b/src/components/shared/frame/UserList/index.tsx @@ -35,6 +35,7 @@ import { setSearchInput } from 'features/appManagement/actions' import { appManagementSelector } from 'features/appManagement/slice' import { isSearchUserEmail } from 'types/Patterns' import { getClientId } from 'services/EnvironmentService' +import { PAGES } from 'types/Constants' interface FetchHookArgsType { appId?: string @@ -87,6 +88,10 @@ export const UserList = ({ const dispatch = useDispatch() const [refresh, setRefresh] = useState(0) const searchInputData = useSelector(appManagementSelector) + const mappedTableSearchTranslation = { + [PAGES.NO_SEARCH_TABLE_DATA]: t('shared.table.emptySearchTable'), + [PAGES.NO_TABLE_DATA]: t('shared.table.emptyTable'), + } const validateSearchText = (expr: string) => { const validateExpr = isSearchUserEmail(expr) @@ -209,6 +214,7 @@ export const UserList = ({ }, ]} disableColumnMenu + mappedTableSearchTranslation={mappedTableSearchTranslation} /> ) diff --git a/src/components/shared/templates/StaticTemplateResponsive/index.tsx b/src/components/shared/templates/StaticTemplateResponsive/index.tsx index cd8d722f9d..62c5473453 100644 --- a/src/components/shared/templates/StaticTemplateResponsive/index.tsx +++ b/src/components/shared/templates/StaticTemplateResponsive/index.tsx @@ -39,6 +39,7 @@ import { uniqueId } from 'lodash' import TitleDescriptionAndSectionlink from './Cards/TitleDescriptionAndSectionlink' import { StandardLibrariesTableColumns } from './Cards/StandardLibrariesTableColumns' import { type StandardLibraryType } from 'features/staticContent/staticContentApiSlice' +import { useTranslation } from 'react-i18next' const TemplateConfig = ({ provider, @@ -239,6 +240,7 @@ export const StaticTemplateResponsive = ({ baseUrl: string stdLibraries?: StandardLibraryType }) => { + const { t } = useTranslation() const [showScroll, setShowScroll] = useState(false) const theme = useTheme() const isMobile = useMediaQuery(theme.breakpoints.down('md'), { @@ -313,6 +315,7 @@ export const StaticTemplateResponsive = ({ rows={stdLibraries.rows} getRowId={(row) => uniqueId(row.uid)} hasBorder={false} + noRowsMsg={t('shared.table.emptyTable')} /> )} diff --git a/src/types/Constants.ts b/src/types/Constants.ts index 3d597a0f97..57793ab24a 100644 --- a/src/types/Constants.ts +++ b/src/types/Constants.ts @@ -110,6 +110,8 @@ export enum PAGES { COMPANY_SUBSCRIPTIONS_DETAIL = 'companySubscriptionsDetail', COMPANY_DATA = 'companyData', ONBOARDING_SERVICE_PROVIDER_MANAGEMENT = 'onboardingServiceProviderManagement', + NO_TABLE_DATA = 'noItemsToDisplay', + NO_SEARCH_TABLE_DATA = 'noSearchItemsToDisplay', } export enum OVERLAYS {