-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Include Settings page for admin and UI to manually import lates…
…t test plan versions (#1290) * Allows navigation to the `/settings` page for the admin * Admin Settings page now includes a "Import Latest Test Plan Versions" button. * Admin Settings page will also display the date of the latest imported test plan version
- Loading branch information
Showing
30 changed files
with
535 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Button } from 'react-bootstrap'; | ||
import { LoadingStatus, useTriggerLoad } from '../common/LoadingStatus'; | ||
import { useThemedModal, THEMES } from '../../hooks/useThemedModal'; | ||
import { dates } from 'shared'; | ||
|
||
const AdminSettings = ({ latestTestPlanVersion, refetch }) => { | ||
const { triggerLoad, loadingMessage, loadingNote } = useTriggerLoad(); | ||
const { | ||
themedModal, | ||
showThemedModal, | ||
setShowThemedModal, | ||
setThemedModalTitle, | ||
setThemedModalContent, | ||
setThemedModalType | ||
} = useThemedModal({ | ||
type: THEMES.SUCCESS, | ||
title: 'Success' | ||
}); | ||
|
||
const handleImportTests = async () => { | ||
await triggerLoad( | ||
async () => { | ||
try { | ||
const response = await fetch('/api/test/import', { method: 'POST' }); | ||
if (!response.ok) { | ||
throw new Error( | ||
`Failed to import the latest Test Plan Versions: ${response.status}` | ||
); | ||
} | ||
|
||
// Success | ||
setThemedModalType(THEMES.SUCCESS); | ||
setThemedModalTitle('Success'); | ||
setThemedModalContent( | ||
<>The latest Test Plan Versions have been imported.</> | ||
); | ||
setShowThemedModal(true); | ||
await refetch(); | ||
} catch (e) { | ||
// Failed, show themed message | ||
setThemedModalType(THEMES.DANGER); | ||
setThemedModalTitle('Error'); | ||
setThemedModalContent(<>{e.message}</>); | ||
setShowThemedModal(true); | ||
} | ||
}, | ||
'Importing latest Test Plan Versions', | ||
'This may take a few minutes ...' | ||
); | ||
}; | ||
|
||
return ( | ||
<LoadingStatus message={loadingMessage} note={loadingNote}> | ||
<section> | ||
<h2>Admin Actions</h2> | ||
<Button variant="primary" onClick={handleImportTests}> | ||
Import Latest Test Plan Versions | ||
</Button> | ||
<p> | ||
Date of latest test plan version:{' '} | ||
{dates.convertDateToString( | ||
latestTestPlanVersion?.updatedAt, | ||
'MMMM D, YYYY HH:mm z' | ||
)} | ||
</p> | ||
</section> | ||
{showThemedModal && themedModal} | ||
</LoadingStatus> | ||
); | ||
}; | ||
|
||
AdminSettings.propTypes = { | ||
latestTestPlanVersion: PropTypes.shape({ | ||
id: PropTypes.string.isRequired, | ||
updatedAt: PropTypes.string.isRequired | ||
}), | ||
refetch: PropTypes.func | ||
}; | ||
|
||
export default AdminSettings; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import React, { useCallback, useEffect, useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Button, Form } from 'react-bootstrap'; | ||
import { useMutation } from '@apollo/client'; | ||
import { TESTER_SETTINGS_QUERY, UPDATE_ME_MUTATION } from './queries'; | ||
import { AtPropType } from '../common/proptypes'; | ||
|
||
const TesterSettings = ({ ats, meAts }) => { | ||
const [updateMe] = useMutation(UPDATE_ME_MUTATION, { | ||
refetchQueries: [{ query: TESTER_SETTINGS_QUERY }] | ||
}); | ||
|
||
const [checkedAts, setCheckedAts] = useState([]); | ||
|
||
if (!ats || !meAts || !checkedAts) return null; | ||
|
||
useEffect(() => { | ||
if (!meAts) return; | ||
setCheckedAts(meAts.map(at => at.id)); | ||
}, [meAts]); | ||
|
||
const handleCheckedAt = useCallback( | ||
event => { | ||
const atId = event.target.id; | ||
const isChecked = checkedAts.includes(atId); | ||
if (isChecked) { | ||
setCheckedAts(checkedAts.filter(item => item !== atId)); | ||
} else { | ||
setCheckedAts([...checkedAts, atId]); | ||
} | ||
}, | ||
[checkedAts] | ||
); | ||
|
||
const handleSave = useCallback( | ||
event => { | ||
event.preventDefault(); | ||
updateMe({ variables: { input: { atIds: checkedAts } } }); | ||
}, | ||
[checkedAts] | ||
); | ||
|
||
const savedAts = meAts.map(at => at.id); | ||
|
||
return ( | ||
<section> | ||
<h2>Assistive Technology Settings</h2> | ||
<div aria-atomic="true" aria-live="polite"> | ||
{savedAts.length > 0 ? ( | ||
<div> | ||
<p data-testid="testable-ats-status"> | ||
You can currently test the following assistive technologies: | ||
</p> | ||
<ul> | ||
{ats | ||
.filter(({ id: atId }) => savedAts.includes(atId)) | ||
.map(at => ( | ||
<li style={{ listStyle: 'disc' }} key={at.id}> | ||
{at.name} | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
) : ( | ||
<p data-testid="testable-ats-status"> | ||
You have not yet selected any assistive technologies. | ||
</p> | ||
)} | ||
</div> | ||
<p> | ||
Update the assistive technologies you can test by selecting from the | ||
options below: | ||
</p> | ||
<Form> | ||
<h3 id="at-group-label">Assistive Technologies</h3> | ||
<Form.Group | ||
controlId="formBasicCheckbox" | ||
role="group" | ||
aria-labelledby="at-group-label" | ||
> | ||
{ats?.map(at => { | ||
return ( | ||
<Form.Check | ||
id={at.id} | ||
key={at.id} | ||
label={at.name} | ||
onChange={handleCheckedAt} | ||
checked={!!checkedAts.find(atId => atId === at.id)} | ||
/> | ||
); | ||
})} | ||
</Form.Group> | ||
<Button variant="primary" type="submit" onClick={handleSave}> | ||
Save | ||
</Button> | ||
</Form> | ||
</section> | ||
); | ||
}; | ||
|
||
TesterSettings.propTypes = { | ||
ats: PropTypes.arrayOf(AtPropType), | ||
meAts: PropTypes.arrayOf(AtPropType) | ||
}; | ||
|
||
export default TesterSettings; |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.