Skip to content

Commit

Permalink
Merge pull request #546 from codeforpdx/536-Enhancement-Confirmation_…
Browse files Browse the repository at this point in the history
…Modal_For_Uploading_Docs

536 enhancement confirmation modal for uploading docs
  • Loading branch information
rioredwards authored Nov 30, 2023
2 parents 5ec692a + 2c15e18 commit 112e683
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 56 deletions.
2 changes: 1 addition & 1 deletion src/components/Form/FormSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const FormSection = ({ title, children }) => {
minWidth: '50%'
}}
>
<Typography align="center" mb={2} sx={{ fontSize: '20px' }}>
<Typography variant="h2" align="center" mb={2} sx={{ fontSize: '20px' }}>
{title}
</Typography>
{children}
Expand Down
45 changes: 30 additions & 15 deletions src/components/Modals/ConfirmationModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,29 @@ import LogoutButton from './LogoutButton';
* @memberof Modals
* @name ConfirmationModal
* @param {object} Props - Props used for ConfirmationModal
* @param {boolean} Props.showConfirmationModal - toggle showing modal
* @param {React.Dispatch<React.SetStateAction<boolean>>} Props.setShowConfirmationModal
* @param {boolean} Props.showModal - toggle showing modal
* @param {React.Dispatch<React.SetStateAction<boolean>>} Props.setShowModal
* - used to close the modal
* @param {string} Props.title - text rendered in dialog title & confirmationButton
* @param {string} Props.text - text rendered in dialog content text
* @param {Function} Props.confirmFunction - method that runs onClick of button
* @param {string} Props.confirmButtonText - text rendered in the confirmation button
* @param {string} Props.cancelButtonText - text rendered in the cancel button
* @param {Function} Props.onConfirm - callback that runs onClick of confirm button
* @param {Function} Props.onCancel - callback that runs onClick of cancel button and after modal is closed (optional)
* @param {boolean} Props.processing - state used to disable button
* @param {boolean} [Props.isLogout] - boolean to wrap button with inrupt logout
* functionality
* @returns {React.JSX.Element} - The confirmation modal
*/
const ConfirmationModal = ({
showConfirmationModal,
setShowConfirmationModal,
title,
text,
confirmFunction,
showModal,
setShowModal,
title = 'Are you sure?',
text = 'Are you sure you want to do this?',
confirmButtonText = 'Confirm',
cancelButtonText = 'Cancel',
onConfirm = () => {},
onCancel = () => {},
processing,
isLogout = false
}) => {
Expand All @@ -49,21 +55,30 @@ const ConfirmationModal = ({
isLogout ? (
<LogoutButton onLogout={() => localStorage.clear()}>
<ConfirmationButton
title={title}
confirmFunction={confirmFunction}
title={confirmButtonText}
confirmFunction={onConfirm}
processing={processing}
/>
</LogoutButton>
) : (
<ConfirmationButton title={title} confirmFunction={confirmFunction} processing={processing} />
<ConfirmationButton
title={confirmButtonText}
confirmFunction={onConfirm}
processing={processing}
/>
);

const handleClose = () => {
setShowModal(false);
onCancel();
};

return (
<Dialog
open={showConfirmationModal}
open={showModal}
aria-labelledby="dialog-title"
aria-describedby="dialog-description"
onClose={() => setShowConfirmationModal(false)}
onClose={handleClose}
>
<DialogTitle id="dialog-title">{title.toUpperCase()}</DialogTitle>

Expand All @@ -86,10 +101,10 @@ const ConfirmationModal = ({
variant="outlined"
color="error"
endIcon={<ClearIcon />}
onClick={() => setShowConfirmationModal(false)}
onClick={handleClose}
fullWidth
>
Cancel
{cancelButtonText}
</Button>
{confirmButton()}
</Box>
Expand Down
64 changes: 64 additions & 0 deletions src/components/Modals/UploadDocumentConfirmationModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// React Imports
import React from 'react';
// Component Imports
import ConfirmationModal from './ConfirmationModal';

// Display text for confirmation modal variants
const confirmationModalContentVariant = {
replace: {
title: 'Replace Document?',
text: 'A file of this name and type already exists on the pod. Would you like to replace it?',
confirmButtonText: 'Replace'
},
add: {
title: 'Upload Document?',
text: 'Are you sure you want to upload this document?',
confirmButtonText: 'Upload'
}
};

/**
* UploadDocumentConfirmationModal Component - Custom ConfirmationModal
* based on the type of document upload (add or replace) that the user is attempting to perform.
*
* @memberof Modals
* @name UploadDocumentModal
* @param {object} Props - Props for UploadDocumentModal component
* @param {boolean} Props.showModal - Boolean for showing/hiding the modal
* @param {React.Dispatch<React.SetStateAction<boolean>>} Props.setShowModal
* - React set function for setting showModal state
* @param {string} Props.uploadType - Type of upload to perform (add or replace)
* @param {Function} Props.onConfirm - Function to run when the user confirms the upload
* @param {Function} Props.onCancel - Function to run when the user cancels the upload
* @returns {React.JSX.Element} The UploadDocumentConfirmationModal Component
*/
const UploadDocumentConfirmationModal = ({
showModal,
setShowModal,
uploadType,
onConfirm,
onCancel
}) => {
const [isProcessing, setIsProcessing] = React.useState(false);
const modalContent = confirmationModalContentVariant[uploadType];

const handleConfirm = async () => {
setIsProcessing(true);
onConfirm();
};

return (
<ConfirmationModal
showModal={showModal}
setShowModal={setShowModal}
title={modalContent.title}
text={modalContent.text}
confirmButtonText={modalContent.confirmButtonText}
onConfirm={handleConfirm}
onCancel={onCancel}
processing={isProcessing}
/>
);
};

export default UploadDocumentConfirmationModal;
76 changes: 54 additions & 22 deletions src/components/Modals/UploadDocumentModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { DocumentListContext } from '@contexts';
import { DocumentSelection, FormSection } from '../Form';
import UploadButtonGroup from './UploadButtonGroup';
import useNotification from '../../hooks/useNotification';
import UploadDocumentConfirmationModal from './UploadDocumentConfirmationModal';

/**
* UploadDocumentModal Component - Component that generates the form for uploading
Expand All @@ -48,6 +49,8 @@ const UploadDocumentModal = ({ showModal, setShowModal }) => {
const [processing, setProcessing] = useState(false);
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [showConfirmationModal, setShowConfirmationModal] = useState(false);
const [confirmationModalType, setConfirmationModalType] = useState('add');

const handleDocType = (event) => {
setDocType(event.target.value);
Expand All @@ -64,45 +67,74 @@ const UploadDocumentModal = ({ showModal, setShowModal }) => {
setShowModal(false);
};

// Event handler for form/document submission to Pod
const handleDocUpload = async (e) => {
e.preventDefault();
setProcessing(true);
const compileDocData = () => ({
name: file.name,
type: docType,
date: expireDate,
description: docDescription
});

const cleanup = () => {
setShowConfirmationModal(false);
setConfirmationModalType('add');
setProcessing(false);
clearInputFields();
};

const fileDesc = {
name: file.name,
type: docType,
date: expireDate,
description: docDescription
};
const handleDocAdd = async () => {
const docData = compileDocData();

try {
await addDocument(fileDesc, file);
await addDocument(docData, file);
addNotification('success', `File uploaded to Solid.`);
cleanup();
} catch (error) {
const confirmationMessage =
'A file of this name and type already exists on the pod. Would you like to replace it?';

switch (error.message) {
case 'File already exists':
if (window.confirm(confirmationMessage)) {
await replaceDocument(fileDesc, file);
addNotification('success', `File updated on Solid.`);
}
// The confirmation modal will prompt the user to replace the file or not
setConfirmationModalType('replace');
setShowConfirmationModal(true);
break;
default:
addNotification('error', `File failed to upload. Reason: ${error.message}`);
}
} finally {
setProcessing(false);
clearInputFields();
}
};

const handleDocReplace = async () => {
const docData = compileDocData();

try {
await replaceDocument(docData, file);
addNotification('success', `File updated on Solid.`);
cleanup();
} catch (error) {
addNotification('error', `File failed to upload. Reason: ${error.message}`);
}
};

const handleUploadCancelled = () => {
setProcessing(false);
};

// Event handler for form/document submission to Pod
const onFormSubmit = async (e) => {
e.preventDefault();
setProcessing(true);
handleDocAdd();
};

return (
<Dialog open={showModal} aria-labelledby="upload-document-dialog" onClose={clearInputFields}>
<UploadDocumentConfirmationModal
showModal={showConfirmationModal}
setShowModal={setShowConfirmationModal}
onCancel={handleUploadCancelled}
onConfirm={confirmationModalType === 'add' ? handleDocAdd : handleDocReplace}
uploadType={confirmationModalType}
/>
<FormSection title="Upload Document">
<form onSubmit={handleDocUpload} autoComplete="off">
<form onSubmit={onFormSubmit} autoComplete="off" style={{ width: '100%' }}>
<FormControlLabel
control={<Switch />}
label="Verify file on upload"
Expand Down
7 changes: 4 additions & 3 deletions src/components/NavBar/NavBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ const NavBar = () => {
{isSmallScreen && <NavbarMobile setShowConfirmation={setShowConfirmationModal} />}
{isLargeScreen && <NavbarDesktop setShowConfirmation={setShowConfirmationModal} />}
<ConfirmationModal
showConfirmationModal={showConfirmationModal}
setShowConfirmationModal={setShowConfirmationModal}
showModal={showConfirmationModal}
setShowModal={setShowConfirmationModal}
title="Log Out"
text="This will log you out of your pod. Are you sure?"
confirmFunction={handleLogout}
onConfirm={handleLogout}
confirmButtonText="Log Out"
processing={processing}
isLogout
/>
Expand Down
7 changes: 4 additions & 3 deletions src/pages/Contacts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ const Contacts = () => {
addContact={addContact}
/>
<ConfirmationModal
showConfirmationModal={showConfirmationModal}
setShowConfirmationModal={setShowConfirmationModal}
showModal={showConfirmationModal}
setShowModal={setShowConfirmationModal}
title="Delete Contact"
text={`Are you sure you want to delete "${selectedContactToDelete?.person}" from your contact list?`}
confirmFunction={handleDeleteContact}
onConfirm={handleDeleteContact}
confirmButtonText="Delete"
processing={processing}
/>
</Container>
Expand Down
7 changes: 4 additions & 3 deletions src/pages/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,12 @@ const Profile = () => {
dataset={dataset}
/>
<ConfirmationModal
showConfirmationModal={showConfirmationModal}
setShowConfirmationModal={setShowConfirmationModal}
showModal={showConfirmationModal}
setShowModal={setShowConfirmationModal}
title="Delete Document"
text={`You're about to delete "${selectedDocToDelete?.name}" from the pod, do you wish to continue?`}
confirmFunction={handleDeleteDoc}
onConfirm={handleDeleteDoc}
confirmButtonText="Delete"
processing={processing}
/>
</Box>
Expand Down
Loading

0 comments on commit 112e683

Please sign in to comment.