Skip to content

Commit

Permalink
Merge pull request #142 from gchq/feature/BAI-257-improve-for-disable…
Browse files Browse the repository at this point in the history
…d-buttons

added a tooltip wrapper for disabled buttons explaining why they're d…
  • Loading branch information
ARADDCC002 authored Sep 21, 2022
2 parents 9c6aa1c + 13ba2e9 commit 726aeda
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 37 deletions.
39 changes: 32 additions & 7 deletions pages/deployment/[uuid].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import Wrapper from '../../src/Wrapper'
import { createDeploymentComplianceFlow } from '../../utils/complianceFlow'
import { postEndpoint } from '../../data/api'
import RawModelExportList from '../../src/RawModelExportList'
import DisabledElementTooltip from '../../src/common/DisabledElementTooltip'
import { VersionDoc } from '../../server/models/Version'
import { ModelUploadType } from '../../types/interfaces'

Expand Down Expand Up @@ -233,12 +234,20 @@ export default function Deployment() {
</Stack>
<Menu anchorEl={anchorEl as HTMLDivElement} open={actionOpen} onClose={handleMenuClose}>
<MenuList>
<MenuItem onClick={requestApprovalReset} disabled={deployment?.managerApproved === 'No Response'}>
<ListItemIcon>
<RestartAlt fontSize='small' />
</ListItemIcon>
<ListItemText>Reset approvals</ListItemText>
</MenuItem>
<DisabledElementTooltip
conditions={[
deployment?.managerApproved === 'No Response'
? 'Deployment needs to be approved before it can have its approvals reset.'
: '',
]}
>
<MenuItem onClick={requestApprovalReset} disabled={deployment?.managerApproved === 'No Response'}>
<ListItemIcon>
<RestartAlt fontSize='small' />
</ListItemIcon>
<ListItemText>Reset approvals</ListItemText>
</MenuItem>
</DisabledElementTooltip>
</MenuList>
</Menu>
<Box sx={{ borderBottom: 1, marginTop: 1, borderColor: 'divider' }}>
Expand All @@ -260,7 +269,23 @@ export default function Deployment() {
}
/>
<Tab label='Settings' value='settings' />
<Tab label='Model Exports' disabled={deployment.managerApproved !== 'Accepted'} value='exports' />
<Tab
style={{ pointerEvents: 'auto' }}
disabled={deployment.managerApproved !== 'Accepted'}
value='exports'
label={
<DisabledElementTooltip
conditions={[
deployment.managerApproved !== 'Accepted'
? 'Deployment needs to be approved before you can view the exported model list.'
: '',
]}
placement='top'
>
Model Exports
</DisabledElementTooltip>
}
/>
</Tabs>
</Box>
<Box sx={{ marginBottom: 3 }} />
Expand Down
91 changes: 61 additions & 30 deletions pages/model/[uuid].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import UpArrow from '@mui/icons-material/KeyboardArrowUpTwoTone'
import PostAddIcon from '@mui/icons-material/PostAddTwoTone'
import RestartAlt from '@mui/icons-material/RestartAltTwoTone'
import UploadIcon from '@mui/icons-material/UploadTwoTone'
import Tooltip from '@mui/material/Tooltip'
import MuiAlert, { AlertProps } from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
Expand Down Expand Up @@ -48,7 +49,8 @@ import ApprovalsChip from '../../src/common/ApprovalsChip'
import EmptyBlob from '../../src/common/EmptyBlob'
import MultipleErrorWrapper from '../../src/errors/MultipleErrorWrapper'
import { lightTheme } from '../../src/theme'
import { Deployment, ModelUploadType, User, Version } from '../../types/interfaces'
import { Deployment, User, Version, ModelUploadType } from '../../types/interfaces'
import DisabledElementTooltip from '../../src/common/DisabledElementTooltip'

const ComplianceFlow = dynamic(() => import('../../src/ComplianceFlow'))

Expand Down Expand Up @@ -205,18 +207,28 @@ function Model() {
</Stack>
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
<MenuList>
<MenuItem
onClick={requestDeployment}
disabled={
!version.built || version.managerApproved !== 'Accepted' || version.reviewerApproved !== 'Accepted'
}
data-test='submitDeployment'
<DisabledElementTooltip
conditions={[
!version.built ? 'Version needs to build.' : '',
version.managerApproved !== 'Accepted' ? 'Waiting on manager approval.' : '',
version.reviewerApproved !== 'Accepted' ? 'Waiting on technical reviewer approval.' : '',
]}
>
<ListItemIcon>
<UploadIcon fontSize='small' />
</ListItemIcon>
<ListItemText>Request deployment</ListItemText>
</MenuItem>
<MenuItem
onClick={requestDeployment}
disabled={
!version.built ||
version.managerApproved !== 'Accepted' ||
version.reviewerApproved !== 'Accepted'
}
data-test='submitDeployment'
>
<ListItemIcon>
<UploadIcon fontSize='small' />
</ListItemIcon>
<ListItemText>Request deployment</ListItemText>
</MenuItem>
</DisabledElementTooltip>
<Divider />
{!modelFavourited && (
<MenuItem onClick={() => setModelFavourite(true)} disabled={favouriteButtonDisabled}>
Expand All @@ -238,33 +250,52 @@ function Model() {
</>
</MenuItem>
)}
<MenuItem
onClick={editModel}
disabled={
(version.managerApproved === 'Accepted' && version.reviewerApproved === 'Accepted') ||
<DisabledElementTooltip
conditions={[
version.managerApproved === 'Accepted' && version.reviewerApproved === 'Accepted'
? 'Version has already been approved by both a manager and a technical reviewer.'
: '',
currentUser.id !== version?.metadata?.contacts?.uploader
}
? 'You do not have permission to edit this model.'
: '',
]}
>
<ListItemIcon>
<EditIcon fontSize='small' />
</ListItemIcon>
<ListItemText>Edit</ListItemText>
</MenuItem>
<MenuItem
onClick={editModel}
disabled={
(version.managerApproved === 'Accepted' && version.reviewerApproved === 'Accepted') ||
currentUser.id !== version?.metadata?.contacts?.uploader
}
>
<ListItemIcon>
<EditIcon fontSize='small' />
</ListItemIcon>
<ListItemText>Edit</ListItemText>
</MenuItem>
</DisabledElementTooltip>
<MenuItem onClick={uploadNewVersion} disabled={currentUser.id !== version.metadata?.contacts?.uploader}>
<ListItemIcon>
<PostAddIcon fontSize='small' />
</ListItemIcon>
<ListItemText>Upload new version</ListItemText>
</MenuItem>
<MenuItem
onClick={requestApprovalReset}
disabled={version.managerApproved === 'No Response' && version.reviewerApproved === 'No Response'}
<DisabledElementTooltip
conditions={[
version.managerApproved === 'No Response' && version.reviewerApproved === 'No Response'
? 'Version needs to have at least one approval before it can have its approvals reset,'
: '',
]}
>
<ListItemIcon>
<RestartAlt fontSize='small' />
</ListItemIcon>
<ListItemText>Reset approvals</ListItemText>
</MenuItem>
<MenuItem
onClick={requestApprovalReset}
disabled={version.managerApproved === 'No Response' && version.reviewerApproved === 'No Response'}
>
<ListItemIcon>
<RestartAlt fontSize='small' />
</ListItemIcon>
<ListItemText>Reset approvals</ListItemText>
</MenuItem>
</DisabledElementTooltip>
</MenuList>
</Menu>
<Stack direction='row' spacing={2}>
Expand Down
25 changes: 25 additions & 0 deletions src/common/DisabledElementTooltip.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @jest-environment jsdom
*/

import Button from '@mui/material/Button'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import DisabledElementTooltip from './DisabledElementTooltip'

describe('DisabledElementTooltip', () => {
const testMessage = 'This ia test message'

it('renders an DisabledElementTooltip component when a button is hovered over', async () => {
render(
<DisabledElementTooltip conditions={[testMessage]}>
<Button data-testid='trigger'>Button</Button>
</DisabledElementTooltip>
)

await waitFor(async () => {
userEvent.hover(screen.getByTestId('trigger'))
expect(await screen.findByText(testMessage)).not.toBeUndefined()
})
})
})
34 changes: 34 additions & 0 deletions src/common/DisabledElementTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { ReactNode, useEffect } from 'react'
import Tooltip, { TooltipProps } from '@mui/material/Tooltip'

function DisabledElementTooltip({
conditions,
children,
placement,
}: {
conditions: string[]
children: ReactNode
placement?: TooltipProps['placement']
}) {
const [titleText, setTitleText] = React.useState<string>('')

useEffect(() => {
if (conditions !== undefined) {
let updatedTitleText = ''
conditions.forEach((condition) => {
if (condition !== '') {
updatedTitleText = `${updatedTitleText} ${condition}`
}
})
setTitleText(updatedTitleText)
}
}, [conditions])

return (
<Tooltip arrow title={titleText} placement={placement || 'right'}>
<div>{children}</div>
</Tooltip>
)
}

export default DisabledElementTooltip

0 comments on commit 726aeda

Please sign in to comment.