Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wmedders21/appeals 59949 #23338

Open
wants to merge 15 commits into
base: feature/APPEALS-49620-and-APPEALS-49626
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/models/tasks/review_transcript_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def available_actions(user)
end

def default_instructions
COPY::REVIEW_TRANSCRIPT_TASK_DEFAULT_INSTRUCTIONS
[COPY::REVIEW_TRANSCRIPT_TASK_DEFAULT_INSTRUCTIONS]
end

def set_assignee
Expand Down
16 changes: 16 additions & 0 deletions client/app/queue/QueueApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import EditAppellantInformation from './editAppellantInformation/EditAppellantIn
import EditPOAInformation from './editPOAInformation/EditPOAInformation';
import NotificationsView from './NotificationsView';
import CavcDashboard from './cavcDashboard/CavcDashboard';
import ErrorsFoundAndCorrectedModal from './components/ErrorsFoundAndCorrectedModal';

class QueueApp extends React.PureComponent {
componentDidMount = () => {
Expand Down Expand Up @@ -684,6 +685,14 @@ class QueueApp extends React.PureComponent {
<CompleteHearingWithdrawalRequestModal {...props.match.params} />
);

routedErrorsFoundAndCorrectedModal = (props) => (
<ErrorsFoundAndCorrectedModal
modalType="errors_found_and_corrected"
{...props.match.params}
closeModal={() => props.history.goBack()}
/>
);

queueName = () =>
this.props.userRole === USER_ROLE_TYPES.attorney ?
'Your Queue' :
Expand Down Expand Up @@ -1381,6 +1390,13 @@ class QueueApp extends React.PureComponent {
title="Return to SCT | Caseflow"
render={this.routedReturnToSctModal}
/>
<PageRoute
exact
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.TRANSCRIPT_ERRORS_FOUND_AND_CORRECTED.value
}`}
title="Transcript Errors found and Corrected | Caseflow"
render={this.routedErrorsFoundAndCorrectedModal}
/>
<PageRoute
exact
path={`/queue/appeals/:appealId/tasks/:taskId/${TASK_ACTIONS.CHANGE_HEARING_REQUEST_TYPE_TO_VIDEO.value
Expand Down
121 changes: 121 additions & 0 deletions client/app/queue/components/ErrorsFoundAndCorrectedModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';

import Modal from '../../components/Modal';
import Button from '../../components/Button';
import FileUpload from '../../components/FileUpload';
import TextareaField from '../../components/TextareaField';

const ErrorsFoundAndCorrectedModal = (props) => {
const [isSubmitDisabled, setIsSubmitDisabled] = useState(true);
const [loading, setLoading] = useState(false);
const [isAnyFileSelected, setIsAnyFileSelected] = useState(false);
const [selectedFile, setSelectedFile] = useState({});
const [fileInputContainerClassName, setFileInputContainerClassName] = useState('cf-file-input-container');
const [notes, setNotes] = useState('');

useEffect(() => {
if (loading) {
setIsSubmitDisabled(true);
} else if (isAnyFileSelected && notes.trim() !== '') {
setIsSubmitDisabled(false);
} else if (notes === '') {
setIsSubmitDisabled(true);
}
}, [loading, isAnyFileSelected, notes]);

const cancel = () => {
props.closeModal();
};

const submit = () => {
// W.I.P.
// This is where we will send the backend request to upload to VBMS.
// selectedFile.file contains the base64 encoded string containing the PDF.
// selectedFile.fileName contains the file's name only.
//
// Not sure yet what we're doing with the notes: maybe saving to the ReviewTranscriptTask instructions,
// in which case we'll need to send props.taskId along with the request.
const requestParams = {
file_info: {
file: selectedFile.file,
file_name: selectedFile.fileName
},
task_info: {
instructions: notes,
task_id: props.taskId
}
};

// setLoading(true);
};

const handleFileChange = (file) => {
setIsAnyFileSelected(true);
setSelectedFile(file);
setFileInputContainerClassName('cf-file-input-container-selected');
};

const handleTextareaFieldChange = (event) => {
setNotes(event);
};

return (
<Modal
title="Upload transcript to VBMS"
closeHandler={cancel}
confirmButton={<Button disabled={isSubmitDisabled} onClick={submit}>Upload to VBMS</Button>}
cancelButton={<Button disabled={loading} linkStyling onClick={cancel}>Cancel</Button>}
>
<p>Please upload the revised transcript file for upload to VBMS.</p>
<strong style={{ color: 'black' }}>Please select PDF</strong>
{!isAnyFileSelected &&
<div className={fileInputContainerClassName}>
<FileUpload
preUploadText="Choose from folder"
id="cf-file-input"
fileType=".pdf"
onChange={handleFileChange}
/>
</div>
}
{isAnyFileSelected &&
<div className="cf-file-container-selected-container">
<div className={fileInputContainerClassName} style={{ borderBottom: '1px solid white' }}>
<div className="cf-file-input-row-element">
<strong style={{ color: 'black' }}>Selected file</strong>
</div>
<div className="cf-file-input-row-element">
<u><FileUpload
preUploadText="Change file"
postUploadText="Change file"
id="usa-file-input"
fileType=".pdf"
onChange={handleFileChange}
/></u>
</div>
</div>
<div className={fileInputContainerClassName} style={{ borderTop: '1px solid white' }}>
{ selectedFile.fileName }
</div>
</div>
}
<div className="comment-size-container">
<TextareaField
id="cf-form-textarea"
name="Please provide context and instructions for this action"
onChange={handleTextareaFieldChange}
value={notes}
/>
</div>
</Modal>
);
};

ErrorsFoundAndCorrectedModal.propTypes = {
closeModal: PropTypes.func,
taskId: PropTypes.string
};

export default ErrorsFoundAndCorrectedModal;

36 changes: 36 additions & 0 deletions client/app/styles/_commons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,42 @@ form {
display: none;
}

.cf-file-input-container {
border: 1px dashed $color-gray-dark;
display: block;
margin-top: .5rem;
margin-bottom: 2rem;
position: relative;
text-align: center;
width: 100%;
padding: 2rem;
}

.cf-file-input-container-selected {
border: 1px dashed $color-gray-dark;
background-color: $color-primary-alt-lightest;
display: flex;
position: relative;
text-align: center;
width: 100%;
padding: 1.5rem;
justify-content: space-between;
}

.cf-file-container-selected-container {
background: none;
border: 2px solid $color-gold;
padding: 2px;
margin-top: 5px;
margin-bottom: 10px;
margin-left: -6px;
margin-right: -6px;
}

.cf-file-input-row-element {
flex-direction: row;
}

//------ Buttons --------*/
[type='submit'],
[type='button'],
Expand Down
3 changes: 2 additions & 1 deletion client/constants/TASK_ACTIONS.json
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,8 @@
"label": "No errors found: Upload transcript to VBMS"
},
"TRANSCRIPT_ERRORS_FOUND_AND_CORRECTED": {
"label": "Errors found and corrected: Upload transcript to VBMS"
"label": "Errors found and corrected: Upload transcript to VBMS",
"value": "modal/errors_found_and_corrected"
},
"CANCEL_REVIEW_TRANSCRIPT_TASK": {
"label": "Cancel task"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { axe } from 'jest-axe';

import ErrorsFoundAndCorrectedModal from 'app/queue/components/ErrorsFoundAndCorrectedModal';

describe('ErrorsFoundAndCorrectedModal', () => {
const closeModal = jest.fn();

const defaultProps = {
taskId: '1000',
closeModal
};

it('renders correctly', () => {
const { container } = render(<ErrorsFoundAndCorrectedModal {...defaultProps} />);

expect(container).toMatchSnapshot();
});

it('passes a11y testing', async () => {
const { container } = render(<ErrorsFoundAndCorrectedModal {...defaultProps} />);

const results = await axe(container);

expect(results).toHaveNoViolations();
});

it('displays the default page elements with default props', () => {
render(
<ErrorsFoundAndCorrectedModal {...defaultProps} />
);

const textarea = screen.getByRole('textbox');

expect(screen.getByText('Upload transcript to VBMS')).toBeInTheDocument();
expect(screen.getByText('Please upload the revised transcript file for upload to VBMS.')).
toBeInTheDocument();
expect(screen.getByText('Please select PDF')).toBeInTheDocument();
expect(screen.getByText('Choose from folder')).toBeInTheDocument();
expect(screen.getByText('Please provide context and instructions for this action')).
toBeInTheDocument();
expect(textarea.value).toBe('');
});

it('can handle a file upload', async () => {
const file = new File(['test'], 'test.pdf', { type: 'application/pdf' });

render(
<ErrorsFoundAndCorrectedModal {...defaultProps} />
);

const input = screen.getByLabelText(/Choose from folder/i);

userEvent.upload(input, file);

await waitFor(() => {
expect(input.files.length).toBe(1);
expect(screen.getByText('test.pdf')).toBeInTheDocument();
expect(screen.getByText('Selected file')).toBeInTheDocument();
expect(screen.getByText('Change file')).toBeInTheDocument();
});
});

it('the submit button is enabled when fields filled out', async () => {
const file = new File(['test'], 'test.pdf', { type: 'application/pdf' });

render(
<ErrorsFoundAndCorrectedModal {...defaultProps} />
);

expect(screen.getByText('Upload to VBMS').closest('button')).
toBeDisabled();

const input = screen.getByLabelText(/Choose from folder/i);
const textarea = screen.getByRole('textbox');

userEvent.upload(input, file);

await waitFor(() => {
expect(screen.getByText('Upload to VBMS').closest('button')).
toBeDisabled();
});

userEvent.type(textarea, 'This is a note.');

await waitFor(() => {
expect(screen.getByText('Upload to VBMS').closest('button')).
toBeEnabled();
});
});
});
Loading
Loading