diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ef345ef..84ccb2830 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ ## Unreleased +## 2.3.0-RC2 + +### Bugfixes + +- **Application Request** + - fixed documents not getting displayed [#1223](https://github.com/eclipse-tractusx/portal-frontend/pull/1223) +- **Use Case Participation** + - fixed columns alignment UI issue [#1247](https://github.com/eclipse-tractusx/portal-frontend/pull/1247) +- **App Overview Details** + - fixed displaying of conformity document in separate section and all other available documents in the documents section [#1235](https://github.com/eclipse-tractusx/portal-frontend/pull/1235) +- **App and Service Subscription Management** [#1246](https://github.com/eclipse-tractusx/portal-frontend/pull/1246) + - fixed showing of all available active apps/services in the filter section + - added heading in each section for the better user experience + - fixed showing of all subscriptions including inactive one in the list +- **App Overview** + - updated the regex for search validation for numeric and special characters [#1179] (https://github.com/eclipse-tractusx/portal-frontend/pull/1179) + ## 2.3.0-RC1 ### Change diff --git a/package.json b/package.json index 60fa9c4ef..72f3dea99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@catena-x/portal-frontend", - "version": "v2.3.0-RC1", + "version": "v2.3.0-RC2", "description": "Catena-X Portal Frontend", "author": "Catena-X Contributors", "license": "Apache-2.0", diff --git a/src/assets/locales/de/main.json b/src/assets/locales/de/main.json index 2e38d65f9..b525f4fe2 100644 --- a/src/assets/locales/de/main.json +++ b/src/assets/locales/de/main.json @@ -1242,7 +1242,12 @@ "message": "Das unten definierte technische Benutzerprofil zeigt die Benutzerberechtigung an, die dem technischen Benutzer, der im Rahmen der App-/Dienstaktivierung erstellt wurde, automatisch zugewiesen wird." }, "pendingTooltip": "Application subscription is pending. The app provider is informed", - "subscribedTooltip": "Die App ist bereits von Ihrem Unternehmen abonniert." + "subscribedTooltip": "Die App ist bereits von Ihrem Unternehmen abonniert.", + "document": { + "noDocumentsAvailable": "No documents available", + "conformityDocument": "Conformity Document", + "conformityDocumentsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + } }, "apprelease": { "headerTitle": "App Release Process", diff --git a/src/assets/locales/de/servicerelease.json b/src/assets/locales/de/servicerelease.json index 532e69ea8..d0231ecb7 100644 --- a/src/assets/locales/de/servicerelease.json +++ b/src/assets/locales/de/servicerelease.json @@ -202,7 +202,8 @@ "url": "URL:", "technicaluserType": "Assigned Permissions:", "close": "Close" - } + }, + "offersHeading": "Services Offered" }, "adminBoard": { "headerTitle": "Service request management", diff --git a/src/assets/locales/en/main.json b/src/assets/locales/en/main.json index 8ce25b01e..9dba6ca83 100644 --- a/src/assets/locales/en/main.json +++ b/src/assets/locales/en/main.json @@ -1211,7 +1211,12 @@ "message": "The technical user profile defined below displays the user permission which the technical user created as part of the app/service activation gets automatically assigned." }, "pendingTooltip": "Application subscription is pending. The app provider is informed", - "subscribedTooltip": "The app is already subscribed by your company" + "subscribedTooltip": "The app is already subscribed by your company", + "document": { + "noDocumentsAvailable": "No documents available", + "conformityDocument": "Conformity Document", + "conformityDocumentsDescription": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + } }, "apprelease": { "headerTitle": "App Release Process", diff --git a/src/assets/locales/en/servicerelease.json b/src/assets/locales/en/servicerelease.json index 8963151bb..9176481e2 100644 --- a/src/assets/locales/en/servicerelease.json +++ b/src/assets/locales/en/servicerelease.json @@ -202,7 +202,8 @@ "url": "URL:", "technicaluserType": "Assigned Permissions:", "close": "Close" - } + }, + "offersHeading": "Services Offered" }, "adminBoard": { "headerTitle": "Service request management", diff --git a/src/components/pages/Admin/components/RegistrationRequests/CompanyDetailOverlay/index.tsx b/src/components/pages/Admin/components/RegistrationRequests/CompanyDetailOverlay/index.tsx index 9977b9e0d..2bb2b28ef 100644 --- a/src/components/pages/Admin/components/RegistrationRequests/CompanyDetailOverlay/index.tsx +++ b/src/components/pages/Admin/components/RegistrationRequests/CompanyDetailOverlay/index.tsx @@ -192,9 +192,10 @@ const CompanyDetailOverlay = ({ key: '', value: ( <> - {company?.documents && company.documents.length > 0 ? ( + {selectedCompany?.documents && + selectedCompany.documents.length > 0 ? ( <> - {company.documents.map( + {selectedCompany.documents.map( (contract: { documentId: string documentType: string diff --git a/src/components/pages/AppDetail/components/AppDetailDocuments/index.tsx b/src/components/pages/AppDetail/components/AppDetailDocuments/index.tsx index 84037c92c..e438732e5 100644 --- a/src/components/pages/AppDetail/components/AppDetailDocuments/index.tsx +++ b/src/components/pages/AppDetail/components/AppDetailDocuments/index.tsx @@ -26,7 +26,10 @@ import { type AppDetails, type Documents } from 'features/apps/types' import { useFetchDocumentByIdMutation } from 'features/apps/apiSlice' import { download } from 'utils/downloadUtils' import '../../AppDetail.scss' -import { DocumentTypeId } from 'features/appManagement/apiSlice' +import { + type DocumentData, + DocumentTypeId, +} from 'features/appManagement/apiSlice' export default function AppDetailDocuments({ item }: { item: AppDetails }) { const { t } = useTranslation() @@ -51,6 +54,35 @@ export default function AppDetailDocuments({ item }: { item: AppDetails }) { } return (
+
+ + {t('content.appdetail.document.conformityDocument')} + + + {t('content.appdetail.document.conformityDocumentsDescription')} + + {item?.documents?.[DocumentTypeId.CONFORMITY_APPROVAL_BUSINESS_APPS] ? ( + item?.documents[DocumentTypeId.CONFORMITY_APPROVAL_BUSINESS_APPS].map( + (item: DocumentData) => ( +
  • + + +
  • + ) + ) + ) : ( + + {t('content.appdetail.document.noDocumentsAvailable')} + + )} +
    {t('content.appdetail.howtouse.heading')} diff --git a/src/components/pages/AppOverview/index.tsx b/src/components/pages/AppOverview/index.tsx index 20441c8c8..e4c39c297 100644 --- a/src/components/pages/AppOverview/index.tsx +++ b/src/components/pages/AppOverview/index.tsx @@ -57,6 +57,7 @@ import { fetchImageWithToken } from 'services/ImageService' import { setCurrentActiveStep } from 'features/appManagement/slice' import { setAppId, setAppStatus } from 'features/appManagement/actions' import NoItems from '../NoItems' +import { isValidAppOverviewSearch } from 'types/Patterns' export default function AppOverview() { const { t } = useTranslation() @@ -222,8 +223,7 @@ export default function AppOverview() { const doSearch = useCallback( (expr: string) => { - const validateExpr = /^[ A-Za-z]*$/.test(expr) - if (!validateExpr) { + if (!isValidAppOverviewSearch(expr)) { return } setSearchExpr(expr) diff --git a/src/components/pages/ServiceSubscription/index.tsx b/src/components/pages/ServiceSubscription/index.tsx index c0e2371fc..6c5527511 100644 --- a/src/components/pages/ServiceSubscription/index.tsx +++ b/src/components/pages/ServiceSubscription/index.tsx @@ -55,6 +55,7 @@ export default function ServiceSubscription() { }} doNotShowAutoSetup={true} type={SubscriptionTypes.SERVICE_SUBSCRIPTION} + activeAppHeading={t('serviceSubscription.offersHeading')} /> ) } diff --git a/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss b/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss index 64f98c3c3..d676765e1 100644 --- a/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss +++ b/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss @@ -68,7 +68,7 @@ padding: 30px; } .useCase-list-main { - max-width: 850px; + max-width: 1200px; width: 100%; margin: 0 auto 50px; .progress-main { @@ -99,6 +99,9 @@ } .credential-list { list-style: none; + .MuiAccordionSummary-root { + padding: 0px 25px 0px 0px; + } .credential-list-item { width: 100%; margin-bottom: 0; diff --git a/src/components/pages/UsecaseParticipation/index.tsx b/src/components/pages/UsecaseParticipation/index.tsx index e348fefc3..a9d730d70 100644 --- a/src/components/pages/UsecaseParticipation/index.tsx +++ b/src/components/pages/UsecaseParticipation/index.tsx @@ -117,7 +117,7 @@ export default function UsecaseParticipation() { : 'N/A'} - {expiryDate.diff(todayDate, 'day') > 0 && ( + {expiryDate.diff(todayDate, 'day') > 0 ? ( + ) : ( +
    )}
    ) @@ -238,7 +240,7 @@ export default function UsecaseParticipation() {
    void isSuccess: boolean + subscriptionHeading: string }) { const theme = useTheme() const { t } = useTranslation() @@ -276,12 +278,14 @@ export default function SubscriptionElements({ return (
    {subscriptions?.length ? ( -
      - {subscriptions.map((subscriptionData) => { - return subscriptionData.companySubscriptionStatuses.map( - (subscription) => - subscription.offerSubscriptionStatus !== - SubscriptionStatus.INACTIVE && ( + <> + + {subscriptionHeading} + +
        + {subscriptions.map((subscriptionData) => { + return subscriptionData.companySubscriptionStatuses.map( + (subscription) => (
      • ) - ) - })} -
      + ) + })} +
    + ) : (
    boolean loadMoreButtonText?: string type?: string + activeAppHeading?: string + subscriptionHeading?: string } export default function Subscription({ @@ -277,6 +279,8 @@ export default function Subscription({ currentSuccessType, loadMoreButtonText = 'Load More', type = SubscriptionTypes.APP_SUBSCRIPTION, + activeAppHeading = 'Apps Offered', + subscriptionHeading = 'Subscriptions', }: SubscriptionType) { const dispatch = useDispatch() const theme = useTheme() @@ -323,23 +327,13 @@ export default function Subscription({ }, [data]) useEffect(() => { - if (data?.content && appFiltersData) { - const fillers: AppFiltersResponse[] = [] - appFiltersData.forEach((item) => { - data.content.forEach((base: { offerId: string }) => { - if (base.offerId === item.id) { - fillers.push(item) - } - }) + if (appFiltersData?.length) { + setState({ + type: ActionKind.SET_APP_FILTERS, + payload: appFiltersData, }) - if (fillers?.length) { - setState({ - type: ActionKind.SET_APP_FILTERS, - payload: fillers, - }) - } } - }, [appFiltersData, data]) + }, [appFiltersData, type]) const setView = (e: React.MouseEvent) => { let status = '' @@ -552,24 +546,27 @@ export default function Subscription({
    {appFilters && appFilters.length > 0 && ( -
    - {appFilters.map((app: AppFiltersResponse) => { - return ( - { - handleActiveAppFilter(app.id) - }} - key={app.id} - > - {app.name} - - ) - })} -
    + <> + {activeAppHeading} +
    + {appFilters.map((app: AppFiltersResponse) => { + return ( + { + handleActiveAppFilter(app.id) + }} + key={app.id} + > + {app.name} + + ) + })} +
    + )} {isFetching ? (
    @@ -588,6 +585,7 @@ export default function Subscription({ type={type} refetch={refetch} isSuccess={apiSuccess} + subscriptionHeading={subscriptionHeading} /> )}
    diff --git a/src/features/admin/registration/types.ts b/src/features/admin/registration/types.ts index 121480d0e..dc543f9f7 100644 --- a/src/features/admin/registration/types.ts +++ b/src/features/admin/registration/types.ts @@ -20,6 +20,7 @@ import type { PaginResult } from '@catena-x/portal-shared-components' import { initialPaginResult, RequestState } from 'types/MainTypes' +import { type DocumentMapper } from '../applicationRequestApiSlice' export const name = 'admin/registration' @@ -63,6 +64,7 @@ export type CompanyDetail = { uniqueIds?: Array countryAlpha2Code?: string companyUser: Array + documents: Array } export type RegistrationRequestDocument = { diff --git a/src/features/serviceSubscription/serviceSubscriptionApiSlice.ts b/src/features/serviceSubscription/serviceSubscriptionApiSlice.ts index eec4c2c5b..56d42e215 100644 --- a/src/features/serviceSubscription/serviceSubscriptionApiSlice.ts +++ b/src/features/serviceSubscription/serviceSubscriptionApiSlice.ts @@ -175,7 +175,7 @@ export const apiSlice = createApi({ }, }), fetchServiceFilters: builder.query({ - query: () => '/api/services/provided', + query: () => '/api/services/provided?statusId=Active', }), fetchServiceSubDetail: builder.query< SubscriptionDetailResponse, diff --git a/src/types/Patterns.test.ts b/src/types/Patterns.test.ts index 803569c30..fa79c6fe2 100644 --- a/src/types/Patterns.test.ts +++ b/src/types/Patterns.test.ts @@ -30,6 +30,7 @@ import { isClientID, isPersonName, isSearchUserEmail, + isValidAppOverviewSearch, } from './Patterns' const TESTDATA = { @@ -255,6 +256,10 @@ const TESTDATA = { ], invalid: ['()*&^%$#/\\?><,`~'], }, + appOverview: { + valid: ['sa-12', '1234', 'Test123!@#'], + invalid: ['🚀 Rocket!', 'Invalid\nNewLine'], + }, } describe('Input Pattern Tests', () => { @@ -354,4 +359,12 @@ describe('Input Pattern Tests', () => { expect(isSearchUserEmail(expr)).toBe(false) }) }) + it('validate appoverview search', () => { + TESTDATA.appOverview.valid.forEach((expr) => { + expect(isValidAppOverviewSearch(expr)).toBe(true) + }) + TESTDATA.appOverview.invalid.forEach((expr) => { + expect(isValidAppOverviewSearch(expr)).toBe(false) + }) + }) }) diff --git a/src/types/Patterns.ts b/src/types/Patterns.ts index c9253a092..0b3994971 100644 --- a/src/types/Patterns.ts +++ b/src/types/Patterns.ts @@ -118,6 +118,9 @@ export const Patterns = { /^(?!.*\s$)(?=[a-zA-Z\d-]{0,10}[-\s]?[a-zA-Z\d-]{0,10}$)[a-zA-Z\d\s-]{2,10}$/, }, EMAIL_SEARCH: /^[ A-Za-z0-9._!@+-]*$/, + appOverview: { + SEARCH: /^[ A-Za-z0-9!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]*$/, + }, } export const isEmpty = (expr: string) => !expr || expr.trim() === '' @@ -208,5 +211,7 @@ export const isPostalCode = (expr: string) => Patterns.companyData.POSTAL_CODE.test(expr) export const isSearchUserEmail = (expr: string) => Patterns.EMAIL_SEARCH.test(expr) +export const isValidAppOverviewSearch = (expr: string) => + Patterns.appOverview.SEARCH.test(expr) export default Patterns