diff --git a/src/assets/locales/de/main.json b/src/assets/locales/de/main.json index 50f1f32e7..9f99bdc5b 100644 --- a/src/assets/locales/de/main.json +++ b/src/assets/locales/de/main.json @@ -1478,7 +1478,9 @@ "placeholder": "Please select", "uploadDocumentTitle": "Please upload your certificate proof:", "note": "Please upload only pdf files with maximum 1 MB.", - "descriptionLabel": "Description for verification" + "descriptionLabel": "Description for verification", + "error": "Something went wrong!", + "success": "Certificate uploaded successfully." }, "successCertificate": { "title": "Certificate successfully uploaded.", @@ -1494,7 +1496,8 @@ "type": "Type: [ISO 9001]", "valid": "Valid until: ", "status": "Status: " - } + }, + "noData": "Derzeit bestehen keine Zertifikate für das Unternehmen. Sie können mit dem Hochladen eines Zertifikats beginnen, indem Sie oben auf die Schaltfläche „Zertifikat hochladen“ klicken." } }, "navigation": { diff --git a/src/assets/locales/en/main.json b/src/assets/locales/en/main.json index 67f883a21..6c9744281 100644 --- a/src/assets/locales/en/main.json +++ b/src/assets/locales/en/main.json @@ -1440,7 +1440,9 @@ "placeholder": "Please select", "uploadDocumentTitle": "Please upload your certificate proof:", "note": "Please upload only pdf files with maximum 1 MB.", - "descriptionLabel": "Description for verification" + "descriptionLabel": "Description for verification", + "error": "Something went wrong!", + "success": "Certificate uploaded successfully." }, "successCertificate": { "title": "Certificate successfully uploaded.", @@ -1456,7 +1458,8 @@ "type": "Type: [ISO 9001]", "valid": "Valid until: ", "status": "Status: " - } + }, + "noData": "Currently there are no certificates for the company. You can start uploading a certificate by clicking the 'Upload Certificate' button above." } }, "navigation": { diff --git a/src/components/overlays/UpdateCertificate/index.tsx b/src/components/overlays/UpdateCertificate/index.tsx index c139f2db2..c87ed1a66 100644 --- a/src/components/overlays/UpdateCertificate/index.tsx +++ b/src/components/overlays/UpdateCertificate/index.tsx @@ -17,6 +17,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +import { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { useDispatch } from 'react-redux' import { Button, Chip, @@ -25,12 +28,9 @@ import { DialogHeader, DropArea, DropAreaProps, + LoadingButton, Typography, } from '@catena-x/portal-shared-components' -import { useTranslation } from 'react-i18next' -import { fetchAny } from 'features/admin/userOwn/actions' -import { useEffect, useState } from 'react' -import { useDispatch } from 'react-redux' import { Box, Dialog } from '@mui/material' import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline' import PendingOutlinedIcon from '@mui/icons-material/PendingOutlined' @@ -38,24 +38,41 @@ import { OVERLAYS } from 'types/Constants' import { closeOverlay, show } from 'features/control/overlay' import { store } from 'features/store' import { Dropzone } from '../../shared/basic/Dropzone' +import { error, success } from 'services/NotifyService' +import { useAddCertificateMutation } from 'features/certification/certificationApiSlice' import './style.scss' export default function UpdateCertificate({ id }: { id: string }) { const { t } = useTranslation() const dispatch = useDispatch() - const [uploadedFile, setUploadedFile] = useState() + const [uploadedFile, setUploadedFile] = useState() const [submitClicked, setSubmitClicked] = useState(false) + const [loading, setLoading] = useState(false) - useEffect(() => { - dispatch(fetchAny(id)) - }, [dispatch, id]) + const [addCertificate] = useAddCertificateMutation() const renderDropArea = (props: DropAreaProps) => { return } - const handleSubmit = () => { - setSubmitClicked(true) + const handleSubmit = async () => { + setLoading(true) + try { + if (uploadedFile) { + const data = { + credentialTypeId: 'credentialType', + document: uploadedFile, + } + await addCertificate(data).unwrap() + setSubmitClicked(true) + setLoading(false) + dispatch(closeOverlay()) + success(t('content.certificates.updateCertificate.success')) + } + } catch (err) { + setLoading(false) + error(t('content.certificates.updateCertificate.error'), '', '') + } } return ( @@ -207,13 +224,28 @@ export default function UpdateCertificate({ id }: { id: string }) { - + + {loading ? ( + {}} + sx={{ marginLeft: '10px' }} + /> + ) : ( + + )} )} diff --git a/src/components/pages/CertificateCredentials/CertificateCredentials.scss b/src/components/pages/CertificateCredentials/CertificateCredentials.scss index ff6b497a0..3970dbabc 100644 --- a/src/components/pages/CertificateCredentials/CertificateCredentials.scss +++ b/src/components/pages/CertificateCredentials/CertificateCredentials.scss @@ -103,4 +103,7 @@ } } } + .noData { + text-align: center; + } } diff --git a/src/components/pages/CertificateCredentials/CertificateElements.tsx b/src/components/pages/CertificateCredentials/CertificateElements.tsx new file mode 100644 index 000000000..759963634 --- /dev/null +++ b/src/components/pages/CertificateCredentials/CertificateElements.tsx @@ -0,0 +1,61 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +import { useTranslation } from 'react-i18next' +import { Grid } from '@mui/material' +import { Typography } from '@catena-x/portal-shared-components' +import { CertificateResponse } from 'features/certification/certificationApiSlice' +import { CertificateCard } from 'components/shared/basic/CertificateCard' +import './CertificateCredentials.scss' + +export interface CertificateProps { + item: CertificateResponse[] +} + +export default function CertificateElements({ data }: any) { + const { t } = useTranslation() + + if (data && data.length === 0) { + return ( + + {t('content.certificates.noData')} + + ) + } + + return ( + + {data?.map((item: CertificateResponse) => ( + + + + ))} + + ) +} diff --git a/src/components/pages/CertificateCredentials/index.tsx b/src/components/pages/CertificateCredentials/index.tsx index b45d2fe74..0e2d2c28d 100644 --- a/src/components/pages/CertificateCredentials/index.tsx +++ b/src/components/pages/CertificateCredentials/index.tsx @@ -19,7 +19,6 @@ import { useReducer, useCallback } from 'react' import { useTranslation, Trans } from 'react-i18next' -import { Grid } from '@mui/material' import { useDispatch } from 'react-redux' import { show } from 'features/control/overlay' import { @@ -32,11 +31,8 @@ import { import SortImage from 'components/shared/frame/SortImage' import './CertificateCredentials.scss' import { OVERLAYS } from 'types/Constants' -import { - CertificateResponse, - useFetchCertificatesQuery, -} from 'features/certification/certificationApiSlice' -import { CertificateCard } from 'components/shared/basic/CertificateCard' +import { useFetchCertificatesQuery } from 'features/certification/certificationApiSlice' +import CertificateElements from './CertificateElements' enum FilterType { UPLOADED = 'Uploaded', @@ -234,23 +230,7 @@ export default function CertificateCredentials() { {t('content.certificates.uploadCertificate')} - - {data?.map((item: CertificateResponse) => ( - - - - ))} - +
diff --git a/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss b/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss index e3f02172b..f953950ba 100644 --- a/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss +++ b/src/components/pages/UsecaseParticipation/UsecaseParticipation.scss @@ -105,6 +105,15 @@ } .thirdSection { width: 30%; + color: #0f71cb; + cursor: pointer; + .framework { + display: flex; + } + svg { + font-size: 15px; + margin-top: 3px; + } } .forthSection { width: 35%; diff --git a/src/components/pages/UsecaseParticipation/index.tsx b/src/components/pages/UsecaseParticipation/index.tsx index cbdbd5693..3ae123eb1 100644 --- a/src/components/pages/UsecaseParticipation/index.tsx +++ b/src/components/pages/UsecaseParticipation/index.tsx @@ -25,6 +25,7 @@ import { Typography, } from '@catena-x/portal-shared-components' import PixIcon from '@mui/icons-material/Pix' +import LaunchIcon from '@mui/icons-material/Launch' import uniqueId from 'lodash/uniqueId' import { show } from 'features/control/overlay' import { OVERLAYS } from 'types/Constants' @@ -32,6 +33,7 @@ import { PageBreadcrumb } from 'components/shared/frame/PageBreadcrumb/PageBread import { useFetchUsecaseQuery } from 'features/usecase/usecaseApiSlice' import './UsecaseParticipation.scss' import { SubscriptionStatus } from 'features/apps/apiSlice' +import { Link } from 'react-router-dom' export default function UsecaseParticipation() { const { t } = useTranslation() @@ -156,12 +158,19 @@ export default function UsecaseParticipation() { {t('content.usecaseParticipation.version')} - - {t('content.usecaseParticipation.framework')} - + + + {t('content.usecaseParticipation.framework')} + + { if ( - ssiDetailData?.[0].participationStatus.toLowerCase() === - StatusVariants.active + ssiDetailData?.participationStatus.toLowerCase() === StatusVariants.active ) { return } else if ( - ssiDetailData?.[0].participationStatus.toLowerCase() === + ssiDetailData?.participationStatus.toLowerCase() === StatusVariants.pending ) { return @@ -84,9 +83,9 @@ export const CertificateCard = ({ {renderStatusIcon()} - {ssiDetailData?.[0].participationStatus.toLowerCase() !== + {ssiDetailData?.participationStatus.toLowerCase() !== StatusVariants.active && - ssiDetailData?.[0].participationStatus.toLowerCase() !== + ssiDetailData?.participationStatus.toLowerCase() !== StatusVariants.pending && ( )} @@ -100,14 +99,14 @@ export const CertificateCard = ({ {ssiDetailData && ( {t('content.certificates.certificateCard.valid')} - {ssiDetailData[0].expiryDate.split('T')[0]} + {ssiDetailData.expiryDate.split('T')[0]} )} {t('content.certificates.certificateCard.status')} - {ssiDetailData?.[0].participationStatus ?? StatusEnum.INACTIVE} + {ssiDetailData?.participationStatus ?? StatusEnum.INACTIVE} - {ssiDetailData?.[0].participationStatus.toLowerCase() === + {ssiDetailData?.participationStatus.toLowerCase() === StatusVariants.pending && ( <> @@ -131,7 +130,7 @@ export const CertificateCard = ({ diff --git a/src/features/certification/certificationApiSlice.tsx b/src/features/certification/certificationApiSlice.tsx index 77f6744ad..5945c2880 100644 --- a/src/features/certification/certificationApiSlice.tsx +++ b/src/features/certification/certificationApiSlice.tsx @@ -39,7 +39,12 @@ export type SSIDetailData = { export type CertificateResponse = { credentialType: string - ssiDetailData: SSIDetailData[] | null + ssiDetailData: SSIDetailData | null +} + +export type CertificateRequest = { + credentialTypeId: string + document: File } export const apiSlice = createApi({ @@ -51,7 +56,14 @@ export const apiSlice = createApi({ url: 'api/administration/companydata/certificates', }), }), + addCertificate: builder.mutation({ + query: (body) => ({ + url: 'api/administration/companydata/ssiCertificate', + method: 'POST', + body: body, + }), + }), }), }) -export const { useFetchCertificatesQuery } = apiSlice +export const { useFetchCertificatesQuery, useAddCertificateMutation } = apiSlice diff --git a/src/types/Config.tsx b/src/types/Config.tsx index 05b4ea1c8..6eb4893d9 100644 --- a/src/types/Config.tsx +++ b/src/types/Config.tsx @@ -479,7 +479,7 @@ export const ALL_PAGES: IPage[] = [ }, { name: PAGES.CERTIFICATE_CREDENTIAL, - role: ROLES.MANAGE_COMPANY_CREDENTIALS, + role: ROLES.REQUEST_SSICREDENTIAL, element: , }, { name: PAGES.DATA_SPACE, element: }, diff --git a/src/types/Constants.ts b/src/types/Constants.ts index 2ae68745a..1296bcda4 100644 --- a/src/types/Constants.ts +++ b/src/types/Constants.ts @@ -206,7 +206,7 @@ export enum ROLES { UPDATE_COMPANY_ROLE = 'update_company_role', USECASE_PARTICIPATION = 'add_use_case_participation', SUBMITTED_APPLICATION = 'view_submitted_applications', - MANAGE_COMPANY_CREDENTIALS = 'manage_company_credentials', + REQUEST_SSICREDENTIAL = 'request_ssicredential', } export enum HINTS {