Skip to content

Commit

Permalink
feat(company wallet): add revoke credential (#821)
Browse files Browse the repository at this point in the history
  • Loading branch information
manojava-gk authored May 24, 2024
1 parent 6182518 commit 8b6ee5e
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 19 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## 2.0.0-RC9

### Feature

- Company Wallet
- Revoke credential

### Bugfix

- App Subscription
Expand Down
15 changes: 14 additions & 1 deletion src/assets/locales/de/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,20 @@
"button3": "Erfahren Sie mehr über VCs (in Kürze verfügbar)"
},
"expiry": "Ablauf: ",
"others": "Others"
"others": "Others",
"revokeHint": "Revoke Credential",
"confirmOverlay": {
"title": "Confirm Revoke",
"description": "Do you really want to continue with the revoke credential? If yes, please click on confirm button"
},
"successOverlay": {
"title": "Revoke Credential",
"description": "Der Widerruf Ihrer Zugangsdaten wurde erfolgreich verarbeitet. Mit der erfolgreichen Sperrung verliert der Ausweis seine Gültigkeit. Beachten Sie, dass die Aktion nach dem Widerrufen eines Berechtigungsnachweises nicht mehr rückgängig gemacht werden kann und der Berechtigungsnachweis nicht mehr als gültig anerkannt wird. Wenn Sie die Zugangsdaten erneut anfordern möchten, starten Sie bitte eine neue Zugangsdatenanfrage."
},
"errorOverlay": {
"title": "Revoke Credential",
"description": "Der Widerruf der Berechtigung war erfolglos. Bitte wenden Sie sich an den Administrator oder versuchen Sie es später erneut."
}
},
"standardLibraryTable": {
"version": "Version",
Expand Down
15 changes: 14 additions & 1 deletion src/assets/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -1901,7 +1901,20 @@
"button3": "Get more details of VCs (coming soon)"
},
"expiry": "Expiry: ",
"others": "Others"
"others": "Others",
"revokeHint": "Revoke Credential",
"confirmOverlay": {
"title": "Confirm Revoke",
"description": "Do you really want to continue with the revoke credential? If yes, please click on confirm button"
},
"successOverlay": {
"title": "Revoke Credential",
"description": "You credential revocation has been successfully processed. With the successful revocation the credential is no longer valid. Note once a credential is revoked, the action cannot be undone, and the credential will no longer be recognized as valid. If you want to request the credential again, please initiate a new credential request."
},
"errorOverlay": {
"title": "Revoke Credential",
"description": "The revocation of the credential was unsuccessful. Please contact the administrator or try again later."
}
},
"standardLibraryTable": {
"version": "Version",
Expand Down
6 changes: 6 additions & 0 deletions src/components/pages/CompanyWallet/CompanyWallet.scss
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,9 @@
padding: 1px;
// background: linear-gradient(360deg, #033430, #76babb); Enable when gradient is needed
}

.revoke-container {
display: flex;
justify-content: space-between;
align-items: center;
}
101 changes: 101 additions & 0 deletions src/components/pages/CompanyWallet/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/********************************************************************************
* Copyright (c) 2024 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 {
Dialog,
DialogContent,
Button,
DialogActions,
DialogHeader,
CircleProgress,
} from '@catena-x/portal-shared-components'
import { Box } from '@mui/material'
interface OverlayProps {
title: string
description: string
openDialog?: boolean
handleOverlayClose: React.MouseEventHandler
handleConfirmClick: React.MouseEventHandler
loading: boolean
}

const Overlay = ({
title,
description,
openDialog = false,
handleOverlayClose,
handleConfirmClick,
loading,
}: OverlayProps) => {
const { t } = useTranslation()

return (
<Dialog
open={openDialog}
sx={{
'.MuiDialog-paper': {
maxWidth: '45%',
},
}}
>
<DialogHeader title={title} />
<DialogContent>{description}</DialogContent>
<DialogActions>
<Button
variant="outlined"
onClick={(e) => {
handleOverlayClose(e)
}}
>
{t('global.actions.cancel')}
</Button>
{!loading ? (
<Button
variant="contained"
onClick={(e) => {
handleConfirmClick(e)
}}
>
{t('global.actions.confirm')}
</Button>
) : (
<Box
sx={{
width: '110px',
display: 'flex',
justifyContent: 'center',
}}
>
<CircleProgress
size={40}
step={1}
interval={0.1}
colorVariant={'primary'}
variant={'indeterminate'}
thickness={8}
/>
</Box>
)}
</DialogActions>
</Dialog>
)
}

export default Overlay
60 changes: 47 additions & 13 deletions src/components/pages/CompanyWallet/RuleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,26 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

import { Typography } from '@catena-x/portal-shared-components'
import { Tooltips, Typography } from '@catena-x/portal-shared-components'
import './CompanyWallet.scss'
import {
CredentialSubjectStatus,
CredentialType,
type WalletContent,
} from 'features/compayWallet/companyWalletApiSlice'
import dayjs from 'dayjs'
import { useTranslation } from 'react-i18next'
import { Box, Grid } from '@mui/material'
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'

type Hash<T> = Record<string, T>

export default function RuleCard({
sections,
handleRevoke,
}: {
readonly sections: Hash<WalletContent[]>
readonly handleRevoke: (id: string) => void
}): JSX.Element {
const { t } = useTranslation()
const keys = Object.keys(sections)
Expand All @@ -54,6 +58,14 @@ export default function RuleCard({
? CredentialSubjectStatus.INACTIVE
: status

const canShowRevoke = (item: WalletContent) => {
return (
item.status === CredentialSubjectStatus.ACTIVE &&
item?.credentialType !== CredentialType.MEMBERSHIP &&
item.credentialType !== CredentialType.BUSINESS_PARTNER_NUMBER
)
}

return (
<>
{keys.map((key) => (
Expand All @@ -78,21 +90,21 @@ export default function RuleCard({
}}
className="grid-layout"
>
{sections[key]?.map((item: WalletContent) => (
{sections[key]?.map((item: WalletContent, index) => (
<Grid
item
xs={4}
sm={4}
md={4}
className="main-rule-card-container"
key={item.expiryDate}
key={item.expiryDate ?? index}
sx={{
paddingLeft: '20px !important',
}}
>
<Box className="gradient-container">
<Box
key={item.expiryDate}
key={item.expiryDate ?? index}
className="rule-card-container"
sx={{
backgroundColor:
Expand Down Expand Up @@ -128,15 +140,37 @@ export default function RuleCard({
<Typography className="text" variant="h4">
{item?.credentialType.split('_').join(' ')}
</Typography>
<div>
<Typography className="text" variant="body3">
{item.authority}
</Typography>
<Typography className="text" variant="body3">
{t('content.companyWallet.expiry')}
{dayjs(item.expiryDate).format('YYYY-MM-DD')}
</Typography>
</div>
<Box className="revoke-container">
<div>
<Typography className="text" variant="body3">
{item.authority}
</Typography>
<Typography className="text" variant="body3">
{t('content.companyWallet.expiry')}
{dayjs(item.expiryDate).format('YYYY-MM-DD')}
</Typography>
</div>
{canShowRevoke(item) && (
<Tooltips
tooltipPlacement="top-start"
tooltipText={t('content.companyWallet.revokeHint')}
children={
<Box
onClick={() => {
handleRevoke(item.credentialDetailId)
}}
>
<SettingsBackupRestoreIcon
sx={{
color: '#c84f4f',
cursor: 'pointer',
}}
/>
</Box>
}
/>
)}
</Box>
</Box>
</Box>
</Grid>
Expand Down
74 changes: 71 additions & 3 deletions src/components/pages/CompanyWallet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
type WalletContent,
useFetchCompanyWalletQuery,
CredentialType,
useRevokeCredentialMutation,
} from 'features/compayWallet/companyWalletApiSlice'
import ComapnyWalletSubNavigationHeader from './ComapnyWalletSubNavigationHeader'
import WalletCard from './WalletCard'
Expand All @@ -32,12 +33,19 @@ import { useEffect, useState } from 'react'
import { groupBy } from 'lodash'
import { Box } from '@mui/material'
import LoadingProgress from 'components/shared/basic/LoadingProgress'
import Overlay from './Overlay'
import { ServerResponseOverlay } from 'components/overlays/ServerResponse'
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'

export default function CompanyWallet(): JSX.Element {
const { t } = useTranslation()
const { data, isSuccess, isError } = useFetchCompanyWalletQuery()
const { data, isSuccess, isError, refetch } = useFetchCompanyWalletQuery()
const [activeWallet, setActiveWallet] = useState<WalletContent[]>([])

const [credentialId, setCredentialId] = useState<string>('')
const [loading, setLoading] = useState<boolean>(false)
const [success, setSuccess] = useState<boolean>(false)
const [error, setError] = useState<boolean>(false)
const [revokeCredential] = useRevokeCredentialMutation()
useEffect(() => {
const actives: WalletContent[] = []
data?.forEach((cont) => {
Expand All @@ -54,6 +62,22 @@ export default function CompanyWallet(): JSX.Element {
: t('content.companyWallet.others')
)

const handleRevocation = async () => {
setLoading(true)
try {
await revokeCredential(credentialId)
.unwrap()
.then(() => {
setSuccess(true)
refetch()
})
} catch (e) {
setError(true)
}
setLoading(false)
setCredentialId('')
}

return (
<main className="companywallet-main">
<div className="companywallet-section">
Expand All @@ -79,7 +103,12 @@ export default function CompanyWallet(): JSX.Element {
<>
<ComapnyWalletSubNavigationHeader />
<div className="container">
<RuleCard sections={groupedItems} />
<RuleCard
handleRevoke={(id) => {
setCredentialId(id)
}}
sections={groupedItems}
/>
</div>
</>
)}
Expand All @@ -97,6 +126,45 @@ export default function CompanyWallet(): JSX.Element {
<LoadingProgress />
</Box>
)}
{credentialId !== '' && (
<Overlay
title={t('content.companyWallet.confirmOverlay.title')}
description={t('content.companyWallet.confirmOverlay.description')}
handleConfirmClick={handleRevocation}
handleOverlayClose={() => {
setCredentialId('')
}}
loading={loading}
openDialog={credentialId !== ''}
/>
)}
{success && (
<ServerResponseOverlay
title={t('content.companyWallet.successOverlay.title')}
intro={t('content.companyWallet.successOverlay.description')}
dialogOpen={true}
handleCallback={() => {
// do nothing
}}
>
<Typography variant="body2"></Typography>
</ServerResponseOverlay>
)}
{error && (
<ServerResponseOverlay
title={t('content.companyWallet.errorOverlay.title')}
intro={t('content.companyWallet.errorOverlay.description')}
dialogOpen={true}
iconComponent={
<ErrorOutlineIcon sx={{ fontSize: 60 }} color="error" />
}
handleCallback={() => {
// do nothing
}}
>
<Typography variant="body2"></Typography>
</ServerResponseOverlay>
)}
</div>
</main>
)
Expand Down
Loading

0 comments on commit 8b6ee5e

Please sign in to comment.